|
|
@ -25,6 +25,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
#include <grpc/support/log.h> |
|
|
|
#include <grpc/support/log.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "src/core/lib/compression/stream_compression.h" |
|
|
|
#include "src/core/lib/debug/stats.h" |
|
|
|
#include "src/core/lib/debug/stats.h" |
|
|
|
#include "src/core/lib/profiling/timers.h" |
|
|
|
#include "src/core/lib/profiling/timers.h" |
|
|
|
#include "src/core/lib/slice/slice_internal.h" |
|
|
|
#include "src/core/lib/slice/slice_internal.h" |
|
|
@ -150,7 +151,11 @@ static void report_stall(grpc_chttp2_transport* t, grpc_chttp2_stream* s, |
|
|
|
":flowed=%" PRId64 ":peer_initwin=%d:t_win=%" PRId64 |
|
|
|
":flowed=%" PRId64 ":peer_initwin=%d:t_win=%" PRId64 |
|
|
|
":s_win=%d:s_delta=%" PRId64 "]", |
|
|
|
":s_win=%d:s_delta=%" PRId64 "]", |
|
|
|
t->peer_string, t, s->id, staller, s->flow_controlled_buffer.length, |
|
|
|
t->peer_string, t, s->id, staller, s->flow_controlled_buffer.length, |
|
|
|
s->compressed_data_buffer.length, s->flow_controlled_bytes_flowed, |
|
|
|
s->stream_compression_method == |
|
|
|
|
|
|
|
GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS |
|
|
|
|
|
|
|
? 0 |
|
|
|
|
|
|
|
: s->compressed_data_buffer.length, |
|
|
|
|
|
|
|
s->flow_controlled_bytes_flowed, |
|
|
|
t->settings[GRPC_ACKED_SETTINGS] |
|
|
|
t->settings[GRPC_ACKED_SETTINGS] |
|
|
|
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE], |
|
|
|
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE], |
|
|
|
t->flow_control->remote_window(), |
|
|
|
t->flow_control->remote_window(), |
|
|
@ -325,7 +330,23 @@ class DataSendContext { |
|
|
|
|
|
|
|
|
|
|
|
bool AnyOutgoing() const { return max_outgoing() > 0; } |
|
|
|
bool AnyOutgoing() const { return max_outgoing() > 0; } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void FlushUncompressedBytes() { |
|
|
|
|
|
|
|
uint32_t send_bytes = static_cast<uint32_t> GPR_MIN( |
|
|
|
|
|
|
|
max_outgoing(), s_->flow_controlled_buffer.length); |
|
|
|
|
|
|
|
is_last_frame_ = send_bytes == s_->flow_controlled_buffer.length && |
|
|
|
|
|
|
|
s_->fetching_send_message == nullptr && |
|
|
|
|
|
|
|
s_->send_trailing_metadata != nullptr && |
|
|
|
|
|
|
|
grpc_metadata_batch_is_empty(s_->send_trailing_metadata); |
|
|
|
|
|
|
|
grpc_chttp2_encode_data(s_->id, &s_->flow_controlled_buffer, send_bytes, |
|
|
|
|
|
|
|
is_last_frame_, &s_->stats.outgoing, &t_->outbuf); |
|
|
|
|
|
|
|
s_->flow_control->SentData(send_bytes); |
|
|
|
|
|
|
|
s_->sending_bytes += send_bytes; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void FlushCompressedBytes() { |
|
|
|
void FlushCompressedBytes() { |
|
|
|
|
|
|
|
GPR_DEBUG_ASSERT(s_->stream_compression_method != |
|
|
|
|
|
|
|
GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS); |
|
|
|
|
|
|
|
|
|
|
|
uint32_t send_bytes = static_cast<uint32_t> GPR_MIN( |
|
|
|
uint32_t send_bytes = static_cast<uint32_t> GPR_MIN( |
|
|
|
max_outgoing(), s_->compressed_data_buffer.length); |
|
|
|
max_outgoing(), s_->compressed_data_buffer.length); |
|
|
|
bool is_last_data_frame = |
|
|
|
bool is_last_data_frame = |
|
|
@ -360,6 +381,9 @@ class DataSendContext { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void CompressMoreBytes() { |
|
|
|
void CompressMoreBytes() { |
|
|
|
|
|
|
|
GPR_DEBUG_ASSERT(s_->stream_compression_method != |
|
|
|
|
|
|
|
GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS); |
|
|
|
|
|
|
|
|
|
|
|
if (s_->stream_compression_ctx == nullptr) { |
|
|
|
if (s_->stream_compression_ctx == nullptr) { |
|
|
|
s_->stream_compression_ctx = |
|
|
|
s_->stream_compression_ctx = |
|
|
|
grpc_stream_compression_context_create(s_->stream_compression_method); |
|
|
|
grpc_stream_compression_context_create(s_->stream_compression_method); |
|
|
@ -417,7 +441,7 @@ class StreamWriteContext { |
|
|
|
// https://github.com/grpc/proposal/blob/master/A6-client-retries.md#when-retries-are-valid
|
|
|
|
// https://github.com/grpc/proposal/blob/master/A6-client-retries.md#when-retries-are-valid
|
|
|
|
if (!t_->is_client && s_->fetching_send_message == nullptr && |
|
|
|
if (!t_->is_client && s_->fetching_send_message == nullptr && |
|
|
|
s_->flow_controlled_buffer.length == 0 && |
|
|
|
s_->flow_controlled_buffer.length == 0 && |
|
|
|
s_->compressed_data_buffer.length == 0 && |
|
|
|
compressed_data_buffer_len() == 0 && |
|
|
|
s_->send_trailing_metadata != nullptr && |
|
|
|
s_->send_trailing_metadata != nullptr && |
|
|
|
is_default_initial_metadata(s_->send_initial_metadata)) { |
|
|
|
is_default_initial_metadata(s_->send_initial_metadata)) { |
|
|
|
ConvertInitialMetadataToTrailingMetadata(); |
|
|
|
ConvertInitialMetadataToTrailingMetadata(); |
|
|
@ -446,6 +470,13 @@ class StreamWriteContext { |
|
|
|
"send_initial_metadata_finished"); |
|
|
|
"send_initial_metadata_finished"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool compressed_data_buffer_len() { |
|
|
|
|
|
|
|
return s_->stream_compression_method == |
|
|
|
|
|
|
|
GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS |
|
|
|
|
|
|
|
? 0 |
|
|
|
|
|
|
|
: s_->compressed_data_buffer.length; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void FlushWindowUpdates() { |
|
|
|
void FlushWindowUpdates() { |
|
|
|
/* send any window updates */ |
|
|
|
/* send any window updates */ |
|
|
|
const uint32_t stream_announce = s_->flow_control->MaybeSendUpdate(); |
|
|
|
const uint32_t stream_announce = s_->flow_control->MaybeSendUpdate(); |
|
|
@ -462,7 +493,7 @@ class StreamWriteContext { |
|
|
|
if (!s_->sent_initial_metadata) return; |
|
|
|
if (!s_->sent_initial_metadata) return; |
|
|
|
|
|
|
|
|
|
|
|
if (s_->flow_controlled_buffer.length == 0 && |
|
|
|
if (s_->flow_controlled_buffer.length == 0 && |
|
|
|
s_->compressed_data_buffer.length == 0) { |
|
|
|
compressed_data_buffer_len() == 0) { |
|
|
|
return; // early out: nothing to do
|
|
|
|
return; // early out: nothing to do
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -479,13 +510,21 @@ class StreamWriteContext { |
|
|
|
return; // early out: nothing to do
|
|
|
|
return; // early out: nothing to do
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
while ((s_->flow_controlled_buffer.length > 0 || |
|
|
|
if (s_->stream_compression_method == |
|
|
|
s_->compressed_data_buffer.length > 0) && |
|
|
|
GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS) { |
|
|
|
data_send_context.max_outgoing() > 0) { |
|
|
|
while (s_->flow_controlled_buffer.length > 0 && |
|
|
|
if (s_->compressed_data_buffer.length > 0) { |
|
|
|
data_send_context.max_outgoing() > 0) { |
|
|
|
data_send_context.FlushCompressedBytes(); |
|
|
|
data_send_context.FlushUncompressedBytes(); |
|
|
|
} else { |
|
|
|
} |
|
|
|
data_send_context.CompressMoreBytes(); |
|
|
|
} else { |
|
|
|
|
|
|
|
while ((s_->flow_controlled_buffer.length > 0 || |
|
|
|
|
|
|
|
s_->compressed_data_buffer.length > 0) && |
|
|
|
|
|
|
|
data_send_context.max_outgoing() > 0) { |
|
|
|
|
|
|
|
if (s_->compressed_data_buffer.length > 0) { |
|
|
|
|
|
|
|
data_send_context.FlushCompressedBytes(); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
data_send_context.CompressMoreBytes(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
write_context_->ResetPingClock(); |
|
|
|
write_context_->ResetPingClock(); |
|
|
@ -495,7 +534,7 @@ class StreamWriteContext { |
|
|
|
data_send_context.CallCallbacks(); |
|
|
|
data_send_context.CallCallbacks(); |
|
|
|
stream_became_writable_ = true; |
|
|
|
stream_became_writable_ = true; |
|
|
|
if (s_->flow_controlled_buffer.length > 0 || |
|
|
|
if (s_->flow_controlled_buffer.length > 0 || |
|
|
|
s_->compressed_data_buffer.length > 0) { |
|
|
|
compressed_data_buffer_len() > 0) { |
|
|
|
GRPC_CHTTP2_STREAM_REF(s_, "chttp2_writing:fork"); |
|
|
|
GRPC_CHTTP2_STREAM_REF(s_, "chttp2_writing:fork"); |
|
|
|
grpc_chttp2_list_add_writable_stream(t_, s_); |
|
|
|
grpc_chttp2_list_add_writable_stream(t_, s_); |
|
|
|
} |
|
|
|
} |
|
|
@ -508,7 +547,7 @@ class StreamWriteContext { |
|
|
|
if (s_->send_trailing_metadata == nullptr) return; |
|
|
|
if (s_->send_trailing_metadata == nullptr) return; |
|
|
|
if (s_->fetching_send_message != nullptr) return; |
|
|
|
if (s_->fetching_send_message != nullptr) return; |
|
|
|
if (s_->flow_controlled_buffer.length != 0) return; |
|
|
|
if (s_->flow_controlled_buffer.length != 0) return; |
|
|
|
if (s_->compressed_data_buffer.length != 0) return; |
|
|
|
if (compressed_data_buffer_len() != 0) return; |
|
|
|
|
|
|
|
|
|
|
|
GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "sending trailing_metadata")); |
|
|
|
GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "sending trailing_metadata")); |
|
|
|
if (grpc_metadata_batch_is_empty(s_->send_trailing_metadata)) { |
|
|
|
if (grpc_metadata_batch_is_empty(s_->send_trailing_metadata)) { |
|
|
|