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

Unified Diff: components/cronet/android/cronet_bidirectional_stream_adapter.cc

Issue 1856073002: Coalesce small buffers in net::BidirectionalStream (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix javadoc Created 4 years, 8 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 side-by-side diff with in-line comments
Download patch
Index: components/cronet/android/cronet_bidirectional_stream_adapter.cc
diff --git a/components/cronet/android/cronet_bidirectional_stream_adapter.cc b/components/cronet/android/cronet_bidirectional_stream_adapter.cc
index a33e4e3627e91f4a9ac45f1e68353c9413b96ae9..84ab85dacb426a7d514dcbe09d6d30108a8ce8e9 100644
--- a/components/cronet/android/cronet_bidirectional_stream_adapter.cc
+++ b/components/cronet/android/cronet_bidirectional_stream_adapter.cc
@@ -34,17 +34,34 @@ using base::android::ConvertJavaStringToUTF8;
namespace cronet {
+namespace {
+
+// As |GetArrayLength| makes no guarantees about the returned value (e.g., it
+// may be -1 if |array| is not a valid Java array), provide a safe wrapper
+// that always returns a valid, non-negative size.
+template <typename JavaArrayType>
+size_t SafeGetArrayLength(JNIEnv* env, JavaArrayType jarray) {
+ DCHECK(jarray);
+ jsize length = env->GetArrayLength(jarray);
+ DCHECK_GE(length, 0) << "Invalid array length: " << length;
+ return static_cast<size_t>(std::max(0, length));
+}
+
+} // namespace
+
static jlong CreateBidirectionalStream(
JNIEnv* env,
- const JavaParamRef<jobject>& jbidi_stream,
- jlong jurl_request_context_adapter) {
+ const base::android::JavaParamRef<jobject>& jbidi_stream,
+ jlong jurl_request_context_adapter,
+ jboolean jdisable_auto_flush) {
CronetURLRequestContextAdapter* context_adapter =
reinterpret_cast<CronetURLRequestContextAdapter*>(
jurl_request_context_adapter);
DCHECK(context_adapter);
CronetBidirectionalStreamAdapter* adapter =
- new CronetBidirectionalStreamAdapter(context_adapter, env, jbidi_stream);
+ new CronetBidirectionalStreamAdapter(context_adapter, env, jbidi_stream,
+ jdisable_auto_flush);
return reinterpret_cast<jlong>(adapter);
}
@@ -57,8 +74,13 @@ bool CronetBidirectionalStreamAdapter::RegisterJni(JNIEnv* env) {
CronetBidirectionalStreamAdapter::CronetBidirectionalStreamAdapter(
CronetURLRequestContextAdapter* context,
JNIEnv* env,
- const JavaParamRef<jobject>& jbidi_stream)
- : context_(context), owner_(env, jbidi_stream), stream_failed_(false) {}
+ const base::android::JavaParamRef<jobject>& jbidi_stream,
+ bool disable_auto_flush)
+ : context_(context),
+ owner_(env, jbidi_stream),
+ disable_auto_flush_(disable_auto_flush),
+ write_end_of_stream_(false),
+ stream_failed_(false) {}
CronetBidirectionalStreamAdapter::~CronetBidirectionalStreamAdapter() {
DCHECK(context_->IsOnNetworkThread());
@@ -66,11 +88,11 @@ CronetBidirectionalStreamAdapter::~CronetBidirectionalStreamAdapter() {
jint CronetBidirectionalStreamAdapter::Start(
JNIEnv* env,
- const JavaParamRef<jobject>& jcaller,
- const JavaParamRef<jstring>& jurl,
+ const base::android::JavaParamRef<jobject>& jcaller,
+ const base::android::JavaParamRef<jstring>& jurl,
jint jpriority,
- const JavaParamRef<jstring>& jmethod,
- const JavaParamRef<jobjectArray>& jheaders,
+ const base::android::JavaParamRef<jstring>& jmethod,
+ const base::android::JavaParamRef<jobjectArray>& jheaders,
jboolean jend_of_stream) {
// Prepare request info here to be able to return the error.
std::unique_ptr<net::BidirectionalStreamRequestInfo> request_info(
@@ -104,8 +126,8 @@ jint CronetBidirectionalStreamAdapter::Start(
jboolean CronetBidirectionalStreamAdapter::ReadData(
JNIEnv* env,
- const JavaParamRef<jobject>& jcaller,
- const JavaParamRef<jobject>& jbyte_buffer,
+ const base::android::JavaParamRef<jobject>& jcaller,
+ const base::android::JavaParamRef<jobject>& jbyte_buffer,
jint jposition,
jint jlimit) {
DCHECK_LT(jposition, jlimit);
@@ -126,35 +148,51 @@ jboolean CronetBidirectionalStreamAdapter::ReadData(
return JNI_TRUE;
}
-jboolean CronetBidirectionalStreamAdapter::WriteData(
+jboolean CronetBidirectionalStreamAdapter::WritevData(
JNIEnv* env,
- const JavaParamRef<jobject>& jcaller,
- const JavaParamRef<jobject>& jbyte_buffer,
- jint jposition,
- jint jlimit,
+ const base::android::JavaParamRef<jobject>& jcaller,
+ const base::android::JavaParamRef<jobjectArray>& jbyte_buffers,
+ const base::android::JavaParamRef<jintArray>& jbyte_buffers_pos,
+ const base::android::JavaParamRef<jintArray>& jbyte_buffers_limit,
jboolean jend_of_stream) {
- DCHECK_LE(jposition, jlimit);
-
- void* data = env->GetDirectBufferAddress(jbyte_buffer);
- if (!data)
+ size_t buffers_array_size = SafeGetArrayLength(env, jbyte_buffers.obj());
+ size_t pos_array_size = SafeGetArrayLength(env, jbyte_buffers.obj());
+ size_t limit_array_size = SafeGetArrayLength(env, jbyte_buffers.obj());
+ if (buffers_array_size != pos_array_size ||
+ buffers_array_size != limit_array_size) {
+ DLOG(ERROR) << "Illegal arguments.";
return JNI_FALSE;
+ }
- scoped_refptr<IOBufferWithByteBuffer> write_buffer(
- new IOBufferWithByteBuffer(env, jbyte_buffer, data, jposition, jlimit));
-
- int remaining_capacity = jlimit - jposition;
-
+ IOByteBufferList buffers;
+ for (size_t i = 0; i < buffers_array_size; ++i) {
+ ScopedJavaLocalRef<jobject> jbuffer(
+ env, env->GetObjectArrayElement(jbyte_buffers, i));
+ void* data = env->GetDirectBufferAddress(jbuffer.obj());
+ if (!data)
+ return JNI_FALSE;
+ jint pos;
+ env->GetIntArrayRegion(jbyte_buffers_pos.obj(), i, 1, &pos);
+ jint limit;
+ env->GetIntArrayRegion(jbyte_buffers_limit.obj(), i, 1, &limit);
+ DCHECK_LE(pos, limit);
+ scoped_refptr<IOBufferWithByteBuffer> write_buffer(
+ new IOBufferWithByteBuffer(
+ env, base::android::JavaParamRef<jobject>(env, jbuffer.Release()),
+ data, pos, limit));
+ buffers.push_back(write_buffer);
+ }
context_->PostTaskToNetworkThread(
FROM_HERE,
- base::Bind(&CronetBidirectionalStreamAdapter::WriteDataOnNetworkThread,
- base::Unretained(this), write_buffer, remaining_capacity,
- jend_of_stream));
+ base::Bind(&CronetBidirectionalStreamAdapter::WritevDataOnNetworkThread,
+ base::Unretained(this), buffers, jend_of_stream));
+
return JNI_TRUE;
}
void CronetBidirectionalStreamAdapter::Destroy(
JNIEnv* env,
- const JavaParamRef<jobject>& jcaller,
+ const base::android::JavaParamRef<jobject>& jcaller,
jboolean jsend_on_canceled) {
// Destroy could be called from any thread, including network thread (if
// posting task to executor throws an exception), but is posted, so |this|
@@ -167,11 +205,10 @@ void CronetBidirectionalStreamAdapter::Destroy(
base::Unretained(this), jsend_on_canceled));
}
-void CronetBidirectionalStreamAdapter::OnHeadersSent() {
+void CronetBidirectionalStreamAdapter::OnStreamReady() {
DCHECK(context_->IsOnNetworkThread());
JNIEnv* env = base::android::AttachCurrentThread();
- cronet::Java_CronetBidirectionalStream_onRequestHeadersSent(env,
- owner_.obj());
+ cronet::Java_CronetBidirectionalStream_onStreamReady(env, owner_.obj());
}
void CronetBidirectionalStreamAdapter::OnHeadersReceived(
@@ -217,13 +254,34 @@ void CronetBidirectionalStreamAdapter::OnDataRead(int bytes_read) {
void CronetBidirectionalStreamAdapter::OnDataSent() {
DCHECK(context_->IsOnNetworkThread());
+ DCHECK(!write_buffer_list_.empty());
+
JNIEnv* env = base::android::AttachCurrentThread();
- cronet::Java_CronetBidirectionalStream_onWriteCompleted(
- env, owner_.obj(), write_buffer_->byte_buffer(),
- write_buffer_->initial_position(), write_buffer_->initial_limit());
- // Free the write buffer. This lets the Java ByteBuffer be freed, if the
+ base::android::ScopedJavaLocalRef<jclass> byte_buffer_clazz(
+ env, env->GetObjectClass(write_buffer_list_[0]->byte_buffer()));
+ size_t size = write_buffer_list_.size();
+ jobjectArray jbuffers =
+ env->NewObjectArray(size, byte_buffer_clazz.obj(), NULL);
+ base::android::CheckException(env);
+ std::vector<int> initial_positions;
+ std::vector<int> initial_limits;
+ for (size_t i = 0; i < size; ++i) {
+ env->SetObjectArrayElement(jbuffers, i,
+ write_buffer_list_[i]->byte_buffer());
+ initial_positions.push_back(write_buffer_list_[i]->initial_position());
+ initial_limits.push_back(write_buffer_list_[i]->initial_limit());
+ }
+ ScopedJavaLocalRef<jintArray> jinitial_positions =
+ base::android::ToJavaIntArray(env, initial_positions);
+ ScopedJavaLocalRef<jintArray> jinitial_limits =
+ base::android::ToJavaIntArray(env, initial_limits);
+ // Call into Java.
+ cronet::Java_CronetBidirectionalStream_onWritevCompleted(
+ env, owner_.obj(), jbuffers, jinitial_positions.obj(),
+ jinitial_limits.obj(), write_end_of_stream_);
+ // Free the write buffers. This lets the Java ByteBuffer be freed, if the
// embedder releases it, too.
- write_buffer_ = nullptr;
+ write_buffer_list_.clear();
}
void CronetBidirectionalStreamAdapter::OnTrailersReceived(
@@ -256,7 +314,7 @@ void CronetBidirectionalStreamAdapter::StartOnNetworkThread(
std::move(request_info), context_->GetURLRequestContext()
->http_transaction_factory()
->GetSession(),
- this));
+ disable_auto_flush_, this));
}
void CronetBidirectionalStreamAdapter::ReadDataOnNetworkThread(
@@ -280,13 +338,13 @@ void CronetBidirectionalStreamAdapter::ReadDataOnNetworkThread(
OnDataRead(bytes_read);
}
-void CronetBidirectionalStreamAdapter::WriteDataOnNetworkThread(
- scoped_refptr<IOBufferWithByteBuffer> write_buffer,
- int buffer_size,
+void CronetBidirectionalStreamAdapter::WritevDataOnNetworkThread(
+ const IOByteBufferList& write_buffer_list,
bool end_of_stream) {
DCHECK(context_->IsOnNetworkThread());
- DCHECK(write_buffer);
- DCHECK(!write_buffer_);
+ DCHECK(write_buffer_list_.empty());
+ DCHECK(!write_buffer_list.empty());
+ DCHECK(!write_end_of_stream_);
if (stream_failed_) {
// If stream failed between the time when WriteData is invoked and
@@ -296,8 +354,20 @@ void CronetBidirectionalStreamAdapter::WriteDataOnNetworkThread(
// set to true.
return;
}
- write_buffer_ = write_buffer;
- bidi_stream_->SendData(write_buffer_.get(), buffer_size, end_of_stream);
+
+ write_end_of_stream_ = end_of_stream;
+ std::vector<net::IOBuffer*> buffers;
+ std::vector<int> lengths;
+ for (const auto& buffer : write_buffer_list) {
+ write_buffer_list_.push_back(buffer);
+ buffers.push_back(buffer.get());
+ lengths.push_back(buffer->initial_limit() - buffer->initial_position());
+ }
+ if (buffers.size() == 1) {
+ bidi_stream_->SendData(buffers[0], lengths[0], end_of_stream);
+ } else {
+ bidi_stream_->SendvData(buffers, lengths, end_of_stream);
+ }
}
void CronetBidirectionalStreamAdapter::DestroyOnNetworkThread(

Powered by Google App Engine
This is Rietveld 408576698