diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 8e1c08b3925..8c05bdf59a0 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -2502,14 +2502,14 @@ class ClientChannel::LoadBalancedCall::Metadata std::vector> TestOnlyCopyToVector() override { std::vector> result; - for (grpc_linked_mdelem* entry = batch_->list.head; entry != nullptr; - entry = entry->next) { - if (batch_->idx.named.path != entry) { - result.push_back(std::make_pair( - std::string(StringViewFromSlice(GRPC_MDKEY(entry->md))), - std::string(StringViewFromSlice(GRPC_MDVALUE(entry->md))))); + (*batch_)->ForEach([&](grpc_mdelem md) { + auto key = std::string(StringViewFromSlice(GRPC_MDKEY(md))); + if (key != ":path") { + result.push_back( + std::make_pair(std::move(key), + std::string(StringViewFromSlice(GRPC_MDVALUE(md))))); } - } + }); return result; } @@ -2537,8 +2537,9 @@ class ClientChannel::LoadBalancedCall::LbCallState const LoadBalancingPolicy::BackendMetricData* GetBackendMetricData() override { if (lb_call_->backend_metric_data_ == nullptr) { - grpc_linked_mdelem* md = lb_call_->recv_trailing_metadata_->idx.named - .x_endpoint_load_metrics_bin; + grpc_linked_mdelem* md = (*lb_call_->recv_trailing_metadata_) + ->legacy_index() + ->named.x_endpoint_load_metrics_bin; if (md != nullptr) { lb_call_->backend_metric_data_ = ParseBackendMetricData(GRPC_MDVALUE(md->md), lb_call_->arena_); @@ -2918,7 +2919,8 @@ void ClientChannel::LoadBalancedCall::RecvTrailingMetadataReady( StringViewFromSlice(message)); } else { // Get status from headers. - const auto& fields = self->recv_trailing_metadata_->idx.named; + const auto& fields = + (*self->recv_trailing_metadata_)->legacy_index()->named; GPR_ASSERT(fields.grpc_status != nullptr); grpc_status_code code = grpc_get_status_code_from_metadata(fields.grpc_status->md); diff --git a/src/core/ext/filters/client_channel/health/health_check_client.cc b/src/core/ext/filters/client_channel/health/health_check_client.cc index d8f44552e0a..2523cd509b9 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.cc +++ b/src/core/ext/filters/client_channel/health/health_check_client.cc @@ -558,9 +558,11 @@ void HealthCheckClient::CallState::RecvTrailingMetadataReady( grpc_error_get_status(error, GRPC_MILLIS_INF_FUTURE, &status, nullptr /* slice */, nullptr /* http_error */, nullptr /* error_string */); - } else if (self->recv_trailing_metadata_.idx.named.grpc_status != nullptr) { + } else if ((*self->recv_trailing_metadata_) + .legacy_index() + ->named.grpc_status != nullptr) { status = grpc_get_status_code_from_metadata( - self->recv_trailing_metadata_.idx.named.grpc_status->md); + (*self->recv_trailing_metadata_).legacy_index()->named.grpc_status->md); } if (GRPC_TRACE_FLAG_ENABLED(grpc_health_check_client_trace)) { gpr_log(GPR_INFO, diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc index 5f7d75c0fd4..c407aa1ef8f 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc @@ -101,20 +101,15 @@ static void clr_start_transport_stream_op_batch( // Handle send_initial_metadata. if (batch->send_initial_metadata) { // Grab client stats object from metadata. - grpc_linked_mdelem* client_stats_md = - batch->payload->send_initial_metadata.send_initial_metadata->list.head; - for (; client_stats_md != nullptr; - client_stats_md = client_stats_md->next) { - if (GRPC_SLICE_START_PTR(GRPC_MDKEY(client_stats_md->md)) == - static_cast(grpc_core::kGrpcLbClientStatsMetadataKey)) { - break; - } - } - if (client_stats_md != nullptr) { + auto client_stats_md = + (*batch->payload->send_initial_metadata.send_initial_metadata) + ->Remove(grpc_slice_from_static_string( + grpc_core::kGrpcLbClientStatsMetadataKey)); + if (client_stats_md.has_value()) { grpc_core::GrpcLbClientStats* client_stats = const_cast( reinterpret_cast( - GRPC_SLICE_START_PTR(GRPC_MDVALUE(client_stats_md->md)))); + GRPC_SLICE_START_PTR(*client_stats_md))); if (client_stats != nullptr) { calld->client_stats.reset(client_stats); // Intercept completion. @@ -123,10 +118,6 @@ static void clr_start_transport_stream_op_batch( calld, grpc_schedule_on_exec_ctx); batch->on_complete = &calld->on_complete_for_send; } - // Remove metadata so it doesn't go out on the wire. - grpc_metadata_batch_remove( - batch->payload->send_initial_metadata.send_initial_metadata, - client_stats_md); } } // Intercept completion of recv_initial_metadata. diff --git a/src/core/ext/filters/client_channel/retry_filter.cc b/src/core/ext/filters/client_channel/retry_filter.cc index 975001d9bd2..f364af029a2 100644 --- a/src/core/ext/filters/client_channel/retry_filter.cc +++ b/src/core/ext/filters/client_channel/retry_filter.cc @@ -1565,11 +1565,12 @@ void GetCallStatus(grpc_millis deadline, grpc_metadata_batch* md_batch, *is_lb_drop = true; } } else { - GPR_ASSERT(md_batch->idx.named.grpc_status != nullptr); - *status = - grpc_get_status_code_from_metadata(md_batch->idx.named.grpc_status->md); - if (md_batch->idx.named.grpc_retry_pushback_ms != nullptr) { - *server_pushback_md = &md_batch->idx.named.grpc_retry_pushback_ms->md; + GPR_ASSERT((*md_batch)->legacy_index()->named.grpc_status != nullptr); + *status = grpc_get_status_code_from_metadata( + (*md_batch)->legacy_index()->named.grpc_status->md); + if ((*md_batch)->legacy_index()->named.grpc_retry_pushback_ms != nullptr) { + *server_pushback_md = + &(*md_batch)->legacy_index()->named.grpc_retry_pushback_ms->md; } } GRPC_ERROR_UNREF(error); @@ -1921,15 +1922,16 @@ void RetryFilter::CallData::CallAttempt::BatchData:: // If we've already completed one or more attempts, add the // grpc-retry-attempts header. call_attempt_->send_initial_metadata_storage_ = - static_cast( - calld->arena_->Alloc(sizeof(grpc_linked_mdelem) * - (calld->send_initial_metadata_.list.count + - (calld->num_attempts_completed_ > 0)))); + static_cast(calld->arena_->Alloc( + sizeof(grpc_linked_mdelem) * + (calld->send_initial_metadata_->non_deadline_count() + + (calld->num_attempts_completed_ > 0)))); grpc_metadata_batch_copy(&calld->send_initial_metadata_, &call_attempt_->send_initial_metadata_, call_attempt_->send_initial_metadata_storage_); - if (GPR_UNLIKELY(call_attempt_->send_initial_metadata_.idx.named - .grpc_previous_rpc_attempts != nullptr)) { + if (GPR_UNLIKELY((*call_attempt_->send_initial_metadata_) + .legacy_index() + ->named.grpc_previous_rpc_attempts != nullptr)) { grpc_metadata_batch_remove(&call_attempt_->send_initial_metadata_, GRPC_BATCH_GRPC_PREVIOUS_RPC_ATTEMPTS); } @@ -1940,7 +1942,7 @@ void RetryFilter::CallData::CallAttempt::BatchData:: grpc_error_handle error = grpc_metadata_batch_add_tail( &call_attempt_->send_initial_metadata_, &call_attempt_->send_initial_metadata_storage_ - [calld->send_initial_metadata_.list.count], + [calld->send_initial_metadata_->non_deadline_count()], retry_md, GRPC_BATCH_GRPC_PREVIOUS_RPC_ATTEMPTS); if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) { gpr_log(GPR_ERROR, "error adding retry metadata: %s", @@ -1984,9 +1986,9 @@ void RetryFilter::CallData::CallAttempt::BatchData:: // the filters in the subchannel stack may modify this batch, and we don't // want those modifications to be passed forward to subsequent attempts. call_attempt_->send_trailing_metadata_storage_ = - static_cast( - calld->arena_->Alloc(sizeof(grpc_linked_mdelem) * - calld->send_trailing_metadata_.list.count)); + static_cast(calld->arena_->Alloc( + sizeof(grpc_linked_mdelem) * + calld->send_trailing_metadata_->non_deadline_count())); grpc_metadata_batch_copy(&calld->send_trailing_metadata_, &call_attempt_->send_trailing_metadata_, call_attempt_->send_trailing_metadata_storage_); @@ -2304,9 +2306,9 @@ void RetryFilter::CallData::MaybeCacheSendOpsForBatch(PendingBatch* pending) { GPR_ASSERT(send_initial_metadata_storage_ == nullptr); grpc_metadata_batch* send_initial_metadata = batch->payload->send_initial_metadata.send_initial_metadata; - send_initial_metadata_storage_ = - static_cast(arena_->Alloc( - sizeof(grpc_linked_mdelem) * send_initial_metadata->list.count)); + send_initial_metadata_storage_ = static_cast( + arena_->Alloc(sizeof(grpc_linked_mdelem) * + (*send_initial_metadata)->non_deadline_count())); grpc_metadata_batch_copy(send_initial_metadata, &send_initial_metadata_, send_initial_metadata_storage_); send_initial_metadata_flags_ = @@ -2325,9 +2327,9 @@ void RetryFilter::CallData::MaybeCacheSendOpsForBatch(PendingBatch* pending) { GPR_ASSERT(send_trailing_metadata_storage_ == nullptr); grpc_metadata_batch* send_trailing_metadata = batch->payload->send_trailing_metadata.send_trailing_metadata; - send_trailing_metadata_storage_ = - static_cast(arena_->Alloc( - sizeof(grpc_linked_mdelem) * send_trailing_metadata->list.count)); + send_trailing_metadata_storage_ = static_cast( + arena_->Alloc(sizeof(grpc_linked_mdelem) * + (*send_trailing_metadata)->non_deadline_count())); grpc_metadata_batch_copy(send_trailing_metadata, &send_trailing_metadata_, send_trailing_metadata_storage_); } diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index a3db6096b02..b0249c70e06 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -255,9 +255,9 @@ void GetCallStatus(grpc_status_code* status, grpc_millis deadline, if (error != GRPC_ERROR_NONE) { grpc_error_get_status(error, deadline, status, nullptr, nullptr, nullptr); } else { - if (md_batch->idx.named.grpc_status != nullptr) { + if ((*md_batch)->legacy_index()->named.grpc_status != nullptr) { *status = grpc_get_status_code_from_metadata( - md_batch->idx.named.grpc_status->md); + (*md_batch)->legacy_index()->named.grpc_status->md); } else { *status = GRPC_STATUS_UNKNOWN; } diff --git a/src/core/ext/filters/deadline/deadline_filter.cc b/src/core/ext/filters/deadline/deadline_filter.cc index 8944f5d9d15..c5ba9ba7d05 100644 --- a/src/core/ext/filters/deadline/deadline_filter.cc +++ b/src/core/ext/filters/deadline/deadline_filter.cc @@ -295,7 +295,7 @@ static void deadline_client_start_transport_stream_op_batch( static void recv_initial_metadata_ready(void* arg, grpc_error_handle error) { grpc_call_element* elem = static_cast(arg); server_call_data* calld = static_cast(elem->call_data); - start_timer_if_needed(elem, calld->recv_initial_metadata->deadline); + start_timer_if_needed(elem, (*calld->recv_initial_metadata)->deadline()); // Invoke the next callback. grpc_core::Closure::Run(DEBUG_LOCATION, calld->next_recv_initial_metadata_ready, diff --git a/src/core/ext/filters/fault_injection/fault_injection_filter.cc b/src/core/ext/filters/fault_injection/fault_injection_filter.cc index d8d2bc171a3..49a36b65443 100644 --- a/src/core/ext/filters/fault_injection/fault_injection_filter.cc +++ b/src/core/ext/filters/fault_injection/fault_injection_filter.cc @@ -46,27 +46,27 @@ static_assert( std::is_trivially_destructible>::value, "the active fault counter needs to have a trivially destructible type"); -inline int GetLinkedMetadatumValueInt(grpc_linked_mdelem* md) { +inline int GetMetadatumValueInt(grpc_mdelem md) { int res; - if (absl::SimpleAtoi(StringViewFromSlice(GRPC_MDVALUE(md->md)), &res)) { + if (absl::SimpleAtoi(StringViewFromSlice(GRPC_MDVALUE(md)), &res)) { return res; } else { return -1; } } -inline uint32_t GetLinkedMetadatumValueUnsignedInt(grpc_linked_mdelem* md) { +inline uint32_t GetMetadatumValueUnsignedInt(grpc_mdelem md) { uint32_t res; - if (absl::SimpleAtoi(StringViewFromSlice(GRPC_MDVALUE(md->md)), &res)) { + if (absl::SimpleAtoi(StringViewFromSlice(GRPC_MDVALUE(md)), &res)) { return res; } else { return -1; } } -inline int64_t GetLinkedMetadatumValueInt64(grpc_linked_mdelem* md) { +inline int64_t GetMetadatumValueInt64(grpc_mdelem md) { int64_t res; - if (absl::SimpleAtoi(StringViewFromSlice(GRPC_MDVALUE(md->md)), &res)) { + if (absl::SimpleAtoi(StringViewFromSlice(GRPC_MDVALUE(md)), &res)) { return res; } else { return -1; @@ -347,9 +347,8 @@ void CallData::DecideWhetherToInjectFaults( *fi_policy_); } }; - for (grpc_linked_mdelem* md = initial_metadata->list.head; md != nullptr; - md = md->next) { - absl::string_view key = StringViewFromSlice(GRPC_MDKEY(md->md)); + (*initial_metadata)->ForEach([&](grpc_mdelem md) { + absl::string_view key = StringViewFromSlice(GRPC_MDKEY(md)); // Only perform string comparison if: // 1. Needs to check this header; // 2. The value is not been filled before. @@ -358,31 +357,31 @@ void CallData::DecideWhetherToInjectFaults( copied_policy->abort_code == GRPC_STATUS_OK) && key == fi_policy_->abort_code_header) { maybe_copy_policy_func(); - grpc_status_code_from_int(GetLinkedMetadatumValueInt(md), + grpc_status_code_from_int(GetMetadatumValueInt(md), &copied_policy->abort_code); } if (!fi_policy_->abort_percentage_header.empty() && key == fi_policy_->abort_percentage_header) { maybe_copy_policy_func(); copied_policy->abort_percentage_numerator = - GPR_MIN(GetLinkedMetadatumValueUnsignedInt(md), + GPR_MIN(GetMetadatumValueUnsignedInt(md), fi_policy_->abort_percentage_numerator); } if (!fi_policy_->delay_header.empty() && (copied_policy == nullptr || copied_policy->delay == 0) && key == fi_policy_->delay_header) { maybe_copy_policy_func(); - copied_policy->delay = static_cast( - GPR_MAX(GetLinkedMetadatumValueInt64(md), 0)); + copied_policy->delay = + static_cast(GPR_MAX(GetMetadatumValueInt64(md), 0)); } if (!fi_policy_->delay_percentage_header.empty() && key == fi_policy_->delay_percentage_header) { maybe_copy_policy_func(); copied_policy->delay_percentage_numerator = - GPR_MIN(GetLinkedMetadatumValueUnsignedInt(md), + GPR_MIN(GetMetadatumValueUnsignedInt(md), fi_policy_->delay_percentage_numerator); } - } + }); if (copied_policy != nullptr) fi_policy_ = copied_policy; } // Roll the dice diff --git a/src/core/ext/filters/http/client/http_client_filter.cc b/src/core/ext/filters/http/client/http_client_filter.cc index a671d318720..a2c5b08f98e 100644 --- a/src/core/ext/filters/http/client/http_client_filter.cc +++ b/src/core/ext/filters/http/client/http_client_filter.cc @@ -113,18 +113,18 @@ struct channel_data { static grpc_error_handle client_filter_incoming_metadata( grpc_metadata_batch* b) { - if (b->idx.named.status != nullptr) { + if ((*b)->legacy_index()->named.status != nullptr) { /* If both gRPC status and HTTP status are provided in the response, we * should prefer the gRPC status code, as mentioned in * https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md. */ - if (b->idx.named.grpc_status != nullptr || - grpc_mdelem_static_value_eq(b->idx.named.status->md, + if ((*b)->legacy_index()->named.grpc_status != nullptr || + grpc_mdelem_static_value_eq((*b)->legacy_index()->named.status->md, GRPC_MDELEM_STATUS_200)) { grpc_metadata_batch_remove(b, GRPC_BATCH_STATUS); } else { - char* val = grpc_dump_slice(GRPC_MDVALUE(b->idx.named.status->md), - GPR_DUMP_ASCII); + char* val = grpc_dump_slice( + GRPC_MDVALUE((*b)->legacy_index()->named.status->md), GPR_DUMP_ASCII); std::string msg = absl::StrCat("Received http2 header with status: ", val); grpc_error_handle e = grpc_error_set_str( @@ -142,29 +142,33 @@ static grpc_error_handle client_filter_incoming_metadata( } } - if (b->idx.named.grpc_message != nullptr) { + if ((*b)->legacy_index()->named.grpc_message != nullptr) { grpc_slice pct_decoded_msg = grpc_core::PermissivePercentDecodeSlice( - GRPC_MDVALUE(b->idx.named.grpc_message->md)); - if (grpc_slice_is_equivalent(pct_decoded_msg, - GRPC_MDVALUE(b->idx.named.grpc_message->md))) { + GRPC_MDVALUE((*b)->legacy_index()->named.grpc_message->md)); + if (grpc_slice_is_equivalent( + pct_decoded_msg, + GRPC_MDVALUE((*b)->legacy_index()->named.grpc_message->md))) { grpc_slice_unref_internal(pct_decoded_msg); } else { - grpc_metadata_batch_set_value(b->idx.named.grpc_message, pct_decoded_msg); + grpc_metadata_batch_set_value((*b)->legacy_index()->named.grpc_message, + pct_decoded_msg); } } - if (b->idx.named.content_type != nullptr) { + if ((*b)->legacy_index()->named.content_type != nullptr) { if (!grpc_mdelem_static_value_eq( - b->idx.named.content_type->md, + (*b)->legacy_index()->named.content_type->md, GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)) { - if (grpc_slice_buf_start_eq(GRPC_MDVALUE(b->idx.named.content_type->md), - EXPECTED_CONTENT_TYPE, - EXPECTED_CONTENT_TYPE_LENGTH) && + if (grpc_slice_buf_start_eq( + GRPC_MDVALUE((*b)->legacy_index()->named.content_type->md), + EXPECTED_CONTENT_TYPE, EXPECTED_CONTENT_TYPE_LENGTH) && (GRPC_SLICE_START_PTR(GRPC_MDVALUE( - b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] == + (*b)->legacy_index() + ->named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] == '+' || GRPC_SLICE_START_PTR(GRPC_MDVALUE( - b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] == + (*b)->legacy_index() + ->named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] == ';')) { /* Although the C implementation doesn't (currently) generate them, any custom +-suffix is explicitly valid. */ @@ -174,8 +178,9 @@ static grpc_error_handle client_filter_incoming_metadata( } else { /* TODO(klempner): We're currently allowing this, but we shouldn't see it without a proxy so log for now. */ - char* val = grpc_dump_slice(GRPC_MDVALUE(b->idx.named.content_type->md), - GPR_DUMP_ASCII); + char* val = grpc_dump_slice( + GRPC_MDVALUE((*b)->legacy_index()->named.content_type->md), + GPR_DUMP_ASCII); gpr_log(GPR_INFO, "Unexpected content-type '%s'", val); gpr_free(val); } @@ -315,9 +320,10 @@ static char* slice_buffer_to_string(grpc_slice_buffer* slice_buffer) { static grpc_error_handle update_path_for_get( grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { call_data* calld = static_cast(elem->call_data); - grpc_slice path_slice = - GRPC_MDVALUE(batch->payload->send_initial_metadata.send_initial_metadata - ->idx.named.path->md); + grpc_slice path_slice = GRPC_MDVALUE( + (*batch->payload->send_initial_metadata.send_initial_metadata) + ->legacy_index() + ->named.path->md); /* sum up individual component's lengths and allocate enough memory to * hold combined path+query */ size_t estimated_len = GRPC_SLICE_LENGTH(path_slice); @@ -350,15 +356,13 @@ static grpc_error_handle update_path_for_get( grpc_mdelem_from_slices(GRPC_MDSTR_PATH, path_with_query_slice); grpc_metadata_batch* b = batch->payload->send_initial_metadata.send_initial_metadata; - return grpc_metadata_batch_substitute(b, b->idx.named.path, + return grpc_metadata_batch_substitute(b, (*b)->legacy_index()->named.path, mdelem_path_and_query); } static void remove_if_present(grpc_metadata_batch* batch, grpc_metadata_batch_callouts_index idx) { - if (batch->idx.array[idx] != nullptr) { - grpc_metadata_batch_remove(batch, idx); - } + grpc_metadata_batch_remove(batch, idx); } static void http_client_start_transport_stream_op_batch( diff --git a/src/core/ext/filters/http/client_authority_filter.cc b/src/core/ext/filters/http/client_authority_filter.cc index c1764ec5902..fdb54de8500 100644 --- a/src/core/ext/filters/http/client_authority_filter.cc +++ b/src/core/ext/filters/http/client_authority_filter.cc @@ -56,8 +56,9 @@ void client_authority_start_transport_stream_op_batch( // Handle send_initial_metadata. // If the initial metadata doesn't already contain :authority, add it. if (batch->send_initial_metadata && - batch->payload->send_initial_metadata.send_initial_metadata->idx.named - .authority == nullptr) { + (*batch->payload->send_initial_metadata.send_initial_metadata) + ->legacy_index() + ->named.authority == nullptr) { grpc_error_handle error = grpc_metadata_batch_add_head( batch->payload->send_initial_metadata.send_initial_metadata, &calld->authority_storage, diff --git a/src/core/ext/filters/http/message_compress/message_compress_filter.cc b/src/core/ext/filters/http/message_compress/message_compress_filter.cc index 8359b1fc45d..60f6a7c52ec 100644 --- a/src/core/ext/filters/http/message_compress/message_compress_filter.cc +++ b/src/core/ext/filters/http/message_compress/message_compress_filter.cc @@ -191,13 +191,16 @@ bool CallData::SkipMessageCompression() { // channel's default setting. grpc_compression_algorithm FindCompressionAlgorithm( grpc_metadata_batch* initial_metadata, ChannelData* channeld) { - if (initial_metadata->idx.named.grpc_internal_encoding_request == nullptr) { + if ((*initial_metadata) + ->legacy_index() + ->named.grpc_internal_encoding_request == nullptr) { return channeld->default_compression_algorithm(); } grpc_compression_algorithm compression_algorithm; // Parse the compression algorithm from the initial metadata. - grpc_mdelem md = - initial_metadata->idx.named.grpc_internal_encoding_request->md; + grpc_mdelem md = (*initial_metadata) + ->legacy_index() + ->named.grpc_internal_encoding_request->md; GPR_ASSERT(grpc_compression_algorithm_parse(GRPC_MDVALUE(md), &compression_algorithm)); // Remove this metadata since it's an internal one (i.e., it won't be @@ -272,7 +275,7 @@ grpc_error_handle CallData::ProcessSendInitialMetadata( if (error != GRPC_ERROR_NONE) return error; // Do not overwrite accept-encoding header if it already presents (e.g., added // by some proxy). - if (!initial_metadata->idx.named.accept_encoding) { + if (!(*initial_metadata)->legacy_index()->named.accept_encoding) { error = grpc_metadata_batch_add_tail( initial_metadata, &accept_stream_encoding_storage_, GRPC_MDELEM_ACCEPT_STREAM_ENCODING_FOR_ALGORITHMS( diff --git a/src/core/ext/filters/http/message_compress/message_decompress_filter.cc b/src/core/ext/filters/http/message_compress/message_decompress_filter.cc index 27718e2e24b..8d6b1c8012b 100644 --- a/src/core/ext/filters/http/message_compress/message_decompress_filter.cc +++ b/src/core/ext/filters/http/message_compress/message_decompress_filter.cc @@ -153,7 +153,7 @@ void CallData::OnRecvInitialMetadataReady(void* arg, grpc_error_handle error) { CallData* calld = static_cast(arg); if (error == GRPC_ERROR_NONE) { grpc_linked_mdelem* grpc_encoding = - calld->recv_initial_metadata_->idx.named.grpc_encoding; + (*calld->recv_initial_metadata_)->legacy_index()->named.grpc_encoding; if (grpc_encoding != nullptr) { calld->algorithm_ = DecodeMessageCompressionAlgorithm(grpc_encoding->md); } diff --git a/src/core/ext/filters/http/server/http_server_filter.cc b/src/core/ext/filters/http/server/http_server_filter.cc index e5996749405..e4c24e46230 100644 --- a/src/core/ext/filters/http/server/http_server_filter.cc +++ b/src/core/ext/filters/http/server/http_server_filter.cc @@ -104,15 +104,17 @@ struct channel_data { } // namespace static grpc_error_handle hs_filter_outgoing_metadata(grpc_metadata_batch* b) { - if (b->idx.named.grpc_message != nullptr) { + if ((*b)->legacy_index()->named.grpc_message != nullptr) { grpc_slice pct_encoded_msg = grpc_core::PercentEncodeSlice( - GRPC_MDVALUE(b->idx.named.grpc_message->md), + GRPC_MDVALUE((*b)->legacy_index()->named.grpc_message->md), grpc_core::PercentEncodingType::Compatible); - if (grpc_slice_is_equivalent(pct_encoded_msg, - GRPC_MDVALUE(b->idx.named.grpc_message->md))) { + if (grpc_slice_is_equivalent( + pct_encoded_msg, + GRPC_MDVALUE((*b)->legacy_index()->named.grpc_message->md))) { grpc_slice_unref_internal(pct_encoded_msg); } else { - grpc_metadata_batch_set_value(b->idx.named.grpc_message, pct_encoded_msg); + grpc_metadata_batch_set_value((*b)->legacy_index()->named.grpc_message, + pct_encoded_msg); } } return GRPC_ERROR_NONE; @@ -159,18 +161,19 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem, grpc_error_handle error = GRPC_ERROR_NONE; static const char* error_name = "Failed processing incoming headers"; - if (b->idx.named.method != nullptr) { - if (md_strict_equal(b->idx.named.method->md, GRPC_MDELEM_METHOD_POST)) { + if ((*b)->legacy_index()->named.method != nullptr) { + if (md_strict_equal((*b)->legacy_index()->named.method->md, + GRPC_MDELEM_METHOD_POST)) { *calld->recv_initial_metadata_flags &= ~(GRPC_INITIAL_METADATA_CACHEABLE_REQUEST | GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST); - } else if (md_strict_equal(b->idx.named.method->md, + } else if (md_strict_equal((*b)->legacy_index()->named.method->md, GRPC_MDELEM_METHOD_PUT)) { *calld->recv_initial_metadata_flags &= ~GRPC_INITIAL_METADATA_CACHEABLE_REQUEST; *calld->recv_initial_metadata_flags |= GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; - } else if (md_strict_equal(b->idx.named.method->md, + } else if (md_strict_equal((*b)->legacy_index()->named.method->md, GRPC_MDELEM_METHOD_GET)) { *calld->recv_initial_metadata_flags |= GRPC_INITIAL_METADATA_CACHEABLE_REQUEST; @@ -180,7 +183,7 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem, hs_add_error(error_name, &error, grpc_attach_md_to_error( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"), - b->idx.named.method->md)); + (*b)->legacy_index()->named.method->md)); } grpc_metadata_batch_remove(b, GRPC_BATCH_METHOD); } else { @@ -191,13 +194,13 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem, GRPC_ERROR_STR_KEY, grpc_slice_from_static_string(":method"))); } - if (b->idx.named.te != nullptr) { - if (!grpc_mdelem_static_value_eq(b->idx.named.te->md, + if ((*b)->legacy_index()->named.te != nullptr) { + if (!grpc_mdelem_static_value_eq((*b)->legacy_index()->named.te->md, GRPC_MDELEM_TE_TRAILERS)) { hs_add_error(error_name, &error, grpc_attach_md_to_error( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"), - b->idx.named.te->md)); + (*b)->legacy_index()->named.te->md)); } grpc_metadata_batch_remove(b, GRPC_BATCH_TE); } else { @@ -207,15 +210,17 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem, GRPC_ERROR_STR_KEY, grpc_slice_from_static_string("te"))); } - if (b->idx.named.scheme != nullptr) { - if (!md_strict_equal(b->idx.named.scheme->md, GRPC_MDELEM_SCHEME_HTTP) && - !md_strict_equal(b->idx.named.scheme->md, GRPC_MDELEM_SCHEME_HTTPS) && - !grpc_mdelem_static_value_eq(b->idx.named.scheme->md, + if ((*b)->legacy_index()->named.scheme != nullptr) { + if (!md_strict_equal((*b)->legacy_index()->named.scheme->md, + GRPC_MDELEM_SCHEME_HTTP) && + !md_strict_equal((*b)->legacy_index()->named.scheme->md, + GRPC_MDELEM_SCHEME_HTTPS) && + !grpc_mdelem_static_value_eq((*b)->legacy_index()->named.scheme->md, GRPC_MDELEM_SCHEME_GRPC)) { hs_add_error(error_name, &error, grpc_attach_md_to_error( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"), - b->idx.named.scheme->md)); + (*b)->legacy_index()->named.scheme->md)); } grpc_metadata_batch_remove(b, GRPC_BATCH_SCHEME); } else { @@ -226,18 +231,20 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem, GRPC_ERROR_STR_KEY, grpc_slice_from_static_string(":scheme"))); } - if (b->idx.named.content_type != nullptr) { + if ((*b)->legacy_index()->named.content_type != nullptr) { if (!grpc_mdelem_static_value_eq( - b->idx.named.content_type->md, + (*b)->legacy_index()->named.content_type->md, GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)) { - if (grpc_slice_buf_start_eq(GRPC_MDVALUE(b->idx.named.content_type->md), - EXPECTED_CONTENT_TYPE, - EXPECTED_CONTENT_TYPE_LENGTH) && + if (grpc_slice_buf_start_eq( + GRPC_MDVALUE((*b)->legacy_index()->named.content_type->md), + EXPECTED_CONTENT_TYPE, EXPECTED_CONTENT_TYPE_LENGTH) && (GRPC_SLICE_START_PTR(GRPC_MDVALUE( - b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] == + (*b)->legacy_index() + ->named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] == '+' || GRPC_SLICE_START_PTR(GRPC_MDVALUE( - b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] == + (*b)->legacy_index() + ->named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] == ';')) { /* Although the C implementation doesn't (currently) generate them, any custom +-suffix is explicitly valid. */ @@ -247,8 +254,9 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem, } else { /* TODO(klempner): We're currently allowing this, but we shouldn't see it without a proxy so log for now. */ - char* val = grpc_dump_slice(GRPC_MDVALUE(b->idx.named.content_type->md), - GPR_DUMP_ASCII); + char* val = grpc_dump_slice( + GRPC_MDVALUE((*b)->legacy_index()->named.content_type->md), + GPR_DUMP_ASCII); gpr_log(GPR_INFO, "Unexpected content-type '%s'", val); gpr_free(val); } @@ -256,7 +264,7 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem, grpc_metadata_batch_remove(b, GRPC_BATCH_CONTENT_TYPE); } - if (b->idx.named.path == nullptr) { + if ((*b)->legacy_index()->named.path == nullptr) { hs_add_error( error_name, &error, grpc_error_set_str( @@ -267,7 +275,7 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem, /* We have a cacheable request made with GET verb. The path contains the * query parameter which is base64 encoded request payload. */ const char k_query_separator = '?'; - grpc_slice path_slice = GRPC_MDVALUE(b->idx.named.path->md); + grpc_slice path_slice = GRPC_MDVALUE((*b)->legacy_index()->named.path->md); uint8_t* path_ptr = GRPC_SLICE_START_PTR(path_slice); size_t path_length = GRPC_SLICE_LENGTH(path_slice); /* offset of the character '?' */ @@ -283,7 +291,7 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem, grpc_mdelem mdelem_path_without_query = grpc_mdelem_from_slices( GRPC_MDSTR_PATH, grpc_slice_sub(path_slice, 0, offset)); - grpc_metadata_batch_substitute(b, b->idx.named.path, + grpc_metadata_batch_substitute(b, (*b)->legacy_index()->named.path, mdelem_path_without_query); /* decode payload from query and add to the slice buffer to be returned */ @@ -304,8 +312,9 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem, } } - if (b->idx.named.host != nullptr && b->idx.named.authority == nullptr) { - grpc_linked_mdelem* el = b->idx.named.host; + if ((*b)->legacy_index()->named.host != nullptr && + (*b)->legacy_index()->named.authority == nullptr) { + grpc_linked_mdelem* el = (*b)->legacy_index()->named.host; grpc_mdelem md = GRPC_MDELEM_REF(el->md); grpc_metadata_batch_remove(b, el); hs_add_error( @@ -318,7 +327,7 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem, GRPC_MDELEM_UNREF(md); } - if (b->idx.named.authority == nullptr) { + if ((*b)->legacy_index()->named.authority == nullptr) { hs_add_error( error_name, &error, grpc_error_set_str( @@ -327,7 +336,8 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem, } channel_data* chand = static_cast(elem->channel_data); - if (!chand->surface_user_agent && b->idx.named.user_agent != nullptr) { + if (!chand->surface_user_agent && + (*b)->legacy_index()->named.user_agent != nullptr) { grpc_metadata_batch_remove(b, GRPC_BATCH_USER_AGENT); } diff --git a/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc b/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc index b2e8f3fd98f..822250ca8d9 100644 --- a/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc +++ b/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc @@ -46,8 +46,8 @@ struct call_data { // Find the user agent metadata element in the batch static bool get_user_agent_mdelem(const grpc_metadata_batch* batch, grpc_mdelem* md) { - if (batch->idx.named.user_agent != nullptr) { - *md = batch->idx.named.user_agent->md; + if ((*batch)->legacy_index()->named.user_agent != nullptr) { + *md = (*batch)->legacy_index()->named.user_agent->md; return true; } return false; diff --git a/src/core/ext/transport/binder/transport/binder_transport.cc b/src/core/ext/transport/binder/transport/binder_transport.cc index dbde0377ba8..63a27d5b871 100644 --- a/src/core/ext/transport/binder/transport/binder_transport.cc +++ b/src/core/ext/transport/binder/transport/binder_transport.cc @@ -375,15 +375,13 @@ static void perform_stream_op_locked(void* stream_op, grpc_binder::Metadata init_md; auto batch = op->payload->send_initial_metadata.send_initial_metadata; - for (grpc_linked_mdelem* md = batch->list.head; md != nullptr; - md = md->next) { - absl::string_view key = - grpc_core::StringViewFromSlice(GRPC_MDKEY(md->md)); + (*batch)->ForEach([&](grpc_mdelem md) { + absl::string_view key = grpc_core::StringViewFromSlice(GRPC_MDKEY(md)); absl::string_view value = - grpc_core::StringViewFromSlice(GRPC_MDVALUE(md->md)); + grpc_core::StringViewFromSlice(GRPC_MDVALUE(md)); gpr_log(GPR_INFO, "send initial metatday key-value %s", absl::StrCat(key, " ", value).c_str()); - if (grpc_slice_eq(GRPC_MDKEY(md->md), GRPC_MDSTR_PATH)) { + if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_PATH)) { // TODO(b/192208403): Figure out if it is correct to simply drop '/' // prefix and treat it as rpc method name GPR_ASSERT(value[0] == '/'); @@ -395,7 +393,7 @@ static void perform_stream_op_locked(void* stream_op, } else { init_md.emplace_back(std::string(key), std::string(value)); } - } + }); tx.SetPrefix(init_md); } if (op->send_message) { @@ -429,25 +427,23 @@ static void perform_stream_op_locked(void* stream_op, auto batch = op->payload->send_trailing_metadata.send_trailing_metadata; grpc_binder::Metadata trailing_metadata; - for (grpc_linked_mdelem* md = batch->list.head; md != nullptr; - md = md->next) { + (*batch)->ForEach([&](grpc_mdelem md) { // Client will not send trailing metadata. GPR_ASSERT(!gbt->is_client); - if (grpc_slice_eq(GRPC_MDKEY(md->md), GRPC_MDSTR_GRPC_STATUS)) { - int status = grpc_get_status_code_from_metadata(md->md); + if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS)) { + int status = grpc_get_status_code_from_metadata(md); gpr_log(GPR_INFO, "send trailing metadata status = %d", status); tx.SetStatus(status); } else { - absl::string_view key = - grpc_core::StringViewFromSlice(GRPC_MDKEY(md->md)); + absl::string_view key = grpc_core::StringViewFromSlice(GRPC_MDKEY(md)); absl::string_view value = - grpc_core::StringViewFromSlice(GRPC_MDVALUE(md->md)); + grpc_core::StringViewFromSlice(GRPC_MDVALUE(md)); gpr_log(GPR_INFO, "send trailing metatday key-value %s", absl::StrCat(key, " ", value).c_str()); trailing_metadata.emplace_back(std::string(key), std::string(value)); } - } + }); // TODO(mingcl): Will we ever has key-value pair here? According to // wireformat client suffix data is always empty. tx.SetSuffix(trailing_metadata); diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index 80b1d31eb7b..290a9dc283f 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -1252,9 +1252,10 @@ void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t, } static bool contains_non_ok_status(grpc_metadata_batch* batch) { - if (batch->idx.named.grpc_status != nullptr) { - return !grpc_mdelem_static_value_eq(batch->idx.named.grpc_status->md, - GRPC_MDELEM_GRPC_STATUS_0); + if ((*batch)->legacy_index()->named.grpc_status != nullptr) { + return !grpc_mdelem_static_value_eq( + (*batch)->legacy_index()->named.grpc_status->md, + GRPC_MDELEM_GRPC_STATUS_0); } return false; } @@ -1349,15 +1350,14 @@ static void complete_fetch_locked(void* gs, grpc_error_handle error) { static void log_metadata(const grpc_metadata_batch* md_batch, uint32_t id, bool is_client, bool is_initial) { - for (grpc_linked_mdelem* md = md_batch->list.head; md != nullptr; - md = md->next) { - char* key = grpc_slice_to_c_string(GRPC_MDKEY(md->md)); - char* value = grpc_slice_to_c_string(GRPC_MDVALUE(md->md)); + (*md_batch)->ForEach([=](grpc_mdelem md) { + char* key = grpc_slice_to_c_string(GRPC_MDKEY(md)); + char* value = grpc_slice_to_c_string(GRPC_MDVALUE(md)); gpr_log(GPR_INFO, "HTTP:%d:%s:%s: %s: %s", id, is_initial ? "HDR" : "TRL", is_client ? "CLI" : "SVR", key, value); gpr_free(key); gpr_free(value); - } + }); } static void perform_stream_op_locked(void* stream_op, @@ -1411,12 +1411,14 @@ static void perform_stream_op_locked(void* stream_op, on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE; // Identify stream compression - if (op_payload->send_initial_metadata.send_initial_metadata->idx.named - .content_encoding == nullptr || + if ((*op_payload->send_initial_metadata.send_initial_metadata) + ->legacy_index() + ->named.content_encoding == nullptr || grpc_stream_compression_method_parse( GRPC_MDVALUE( - op_payload->send_initial_metadata.send_initial_metadata->idx - .named.content_encoding->md), + (*op_payload->send_initial_metadata.send_initial_metadata) + ->legacy_index() + ->named.content_encoding->md), true, &s->stream_compression_method) == 0) { s->stream_compression_method = GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS; } @@ -1430,7 +1432,8 @@ static void perform_stream_op_locked(void* stream_op, s->send_initial_metadata = op_payload->send_initial_metadata.send_initial_metadata; if (t->is_client) { - s->deadline = GPR_MIN(s->deadline, s->send_initial_metadata->deadline); + s->deadline = + GPR_MIN(s->deadline, (*s->send_initial_metadata)->deadline()); } if (contains_non_ok_status(s->send_initial_metadata)) { s->seen_error = true; @@ -1624,12 +1627,14 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs, if (!t->is_client) { if (op->send_initial_metadata) { grpc_millis deadline = - op->payload->send_initial_metadata.send_initial_metadata->deadline; + (*op->payload->send_initial_metadata.send_initial_metadata) + ->deadline(); GPR_ASSERT(deadline == GRPC_MILLIS_INF_FUTURE); } if (op->send_trailing_metadata) { grpc_millis deadline = - op->payload->send_trailing_metadata.send_trailing_metadata->deadline; + (*op->payload->send_trailing_metadata.send_trailing_metadata) + ->deadline(); GPR_ASSERT(deadline == GRPC_MILLIS_INF_FUTURE); } } @@ -2104,16 +2109,13 @@ void grpc_chttp2_fake_status(grpc_chttp2_transport* t, grpc_chttp2_stream* s, gpr_ltoa(status, status_string); GRPC_LOG_IF_ERROR("add_status", grpc_chttp2_incoming_metadata_buffer_replace_or_add( - &s->metadata_buffer[1], - grpc_mdelem_from_slices( - GRPC_MDSTR_GRPC_STATUS, - grpc_core::UnmanagedMemorySlice(status_string)))); + &s->metadata_buffer[1], GRPC_MDSTR_GRPC_STATUS, + grpc_core::UnmanagedMemorySlice(status_string))); if (!GRPC_SLICE_IS_EMPTY(slice)) { GRPC_LOG_IF_ERROR( "add_status_message", grpc_chttp2_incoming_metadata_buffer_replace_or_add( - &s->metadata_buffer[1], - grpc_mdelem_create(GRPC_MDSTR_GRPC_MESSAGE, slice, nullptr))); + &s->metadata_buffer[1], GRPC_MDSTR_GRPC_MESSAGE, slice)); } s->published_metadata[1] = GRPC_METADATA_SYNTHESIZED_FROM_FAKE; grpc_chttp2_maybe_complete_recv_trailing_metadata(t, s); diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.cc b/src/core/ext/transport/chttp2/transport/hpack_parser.cc index 09681faebd3..31cf806266d 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_parser.cc +++ b/src/core/ext/transport/chttp2/transport/hpack_parser.cc @@ -1348,10 +1348,11 @@ static void force_client_rst_stream(void* sp, grpc_error_handle /*error*/) { static void parse_stream_compression_md(grpc_chttp2_transport* /*t*/, grpc_chttp2_stream* s, grpc_metadata_batch* initial_metadata) { - if (initial_metadata->idx.named.content_encoding == nullptr || + if ((*initial_metadata)->legacy_index()->named.content_encoding == nullptr || grpc_stream_compression_method_parse( - GRPC_MDVALUE(initial_metadata->idx.named.content_encoding->md), false, - &s->stream_decompression_method) == 0) { + GRPC_MDVALUE( + (*initial_metadata)->legacy_index()->named.content_encoding->md), + false, &s->stream_decompression_method) == 0) { s->stream_decompression_method = GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS; } diff --git a/src/core/ext/transport/chttp2/transport/incoming_metadata.cc b/src/core/ext/transport/chttp2/transport/incoming_metadata.cc index c803d79d3fe..7cf174b3797 100644 --- a/src/core/ext/transport/chttp2/transport/incoming_metadata.cc +++ b/src/core/ext/transport/chttp2/transport/incoming_metadata.cc @@ -43,21 +43,17 @@ grpc_error_handle grpc_chttp2_incoming_metadata_buffer_add( } grpc_error_handle grpc_chttp2_incoming_metadata_buffer_replace_or_add( - grpc_chttp2_incoming_metadata_buffer* buffer, grpc_mdelem elem) { - for (grpc_linked_mdelem* l = buffer->batch.list.head; l != nullptr; - l = l->next) { - if (grpc_slice_eq(GRPC_MDKEY(l->md), GRPC_MDKEY(elem))) { - GRPC_MDELEM_UNREF(l->md); - l->md = elem; - return GRPC_ERROR_NONE; - } - } - return grpc_chttp2_incoming_metadata_buffer_add(buffer, elem); + grpc_chttp2_incoming_metadata_buffer* buffer, grpc_slice key, + grpc_slice value) { + if (buffer->batch->ReplaceIfExists(key, value)) return GRPC_ERROR_NONE; + return grpc_chttp2_incoming_metadata_buffer_add( + buffer, grpc_mdelem_from_slices(grpc_slice_ref_internal(key), + grpc_slice_ref_internal(value))); } void grpc_chttp2_incoming_metadata_buffer_set_deadline( grpc_chttp2_incoming_metadata_buffer* buffer, grpc_millis deadline) { - buffer->batch.deadline = deadline; + buffer->batch->SetDeadline(deadline); } void grpc_chttp2_incoming_metadata_buffer_publish( diff --git a/src/core/ext/transport/chttp2/transport/incoming_metadata.h b/src/core/ext/transport/chttp2/transport/incoming_metadata.h index 68413b068c7..b5a8faec2c2 100644 --- a/src/core/ext/transport/chttp2/transport/incoming_metadata.h +++ b/src/core/ext/transport/chttp2/transport/incoming_metadata.h @@ -27,7 +27,7 @@ struct grpc_chttp2_incoming_metadata_buffer { explicit grpc_chttp2_incoming_metadata_buffer(grpc_core::Arena* arena) : arena(arena) { grpc_metadata_batch_init(&batch); - batch.deadline = GRPC_MILLIS_INF_FUTURE; + batch->ClearDeadline(); } ~grpc_chttp2_incoming_metadata_buffer() { grpc_metadata_batch_destroy(&batch); @@ -50,8 +50,8 @@ grpc_error_handle grpc_chttp2_incoming_metadata_buffer_add( grpc_chttp2_incoming_metadata_buffer* buffer, grpc_mdelem elem) GRPC_MUST_USE_RESULT; grpc_error_handle grpc_chttp2_incoming_metadata_buffer_replace_or_add( - grpc_chttp2_incoming_metadata_buffer* buffer, - grpc_mdelem elem) GRPC_MUST_USE_RESULT; + grpc_chttp2_incoming_metadata_buffer* buffer, grpc_slice key, + grpc_slice value) GRPC_MUST_USE_RESULT; void grpc_chttp2_incoming_metadata_buffer_set_deadline( grpc_chttp2_incoming_metadata_buffer* buffer, grpc_millis deadline); diff --git a/src/core/ext/transport/chttp2/transport/writing.cc b/src/core/ext/transport/chttp2/transport/writing.cc index ccd694454bf..39fd1f766cf 100644 --- a/src/core/ext/transport/chttp2/transport/writing.cc +++ b/src/core/ext/transport/chttp2/transport/writing.cc @@ -193,7 +193,8 @@ static uint32_t target_write_size(grpc_chttp2_transport* /*t*/) { // Returns true if initial_metadata contains only default headers. static bool is_default_initial_metadata(grpc_metadata_batch* initial_metadata) { - return initial_metadata->list.default_count == initial_metadata->list.count; + return (*initial_metadata)->default_count() == + (*initial_metadata)->non_deadline_count(); } namespace { @@ -468,7 +469,7 @@ class StreamWriteContext { [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE], // max_frame_size &s_->stats.outgoing // stats }, - *s_->send_initial_metadata, &t_->outbuf); + **s_->send_initial_metadata, &t_->outbuf); grpc_chttp2_reset_ping_clock(t_); write_context_->IncInitialMetadataWrites(); } @@ -579,7 +580,7 @@ class StreamWriteContext { grpc_core::MetadataArray( extra_headers_for_trailing_metadata_, num_extra_headers_for_trailing_metadata_), - *s_->send_trailing_metadata), + **s_->send_trailing_metadata), &t_->outbuf); } write_context_->IncTrailingMetadataWrites(); @@ -600,15 +601,18 @@ class StreamWriteContext { gpr_log(GPR_INFO, "not sending initial_metadata (Trailers-Only)")); // When sending Trailers-Only, we need to move the :status and // content-type headers to the trailers. - if (s_->send_initial_metadata->idx.named.status != nullptr) { + if ((*s_->send_initial_metadata)->legacy_index()->named.status != nullptr) { extra_headers_for_trailing_metadata_ [num_extra_headers_for_trailing_metadata_++] = - &s_->send_initial_metadata->idx.named.status->md; + &(*s_->send_initial_metadata)->legacy_index()->named.status->md; } - if (s_->send_initial_metadata->idx.named.content_type != nullptr) { + if ((*s_->send_initial_metadata)->legacy_index()->named.content_type != + nullptr) { extra_headers_for_trailing_metadata_ [num_extra_headers_for_trailing_metadata_++] = - &s_->send_initial_metadata->idx.named.content_type->md; + &(*s_->send_initial_metadata) + ->legacy_index() + ->named.content_type->md; } } diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.cc b/src/core/ext/transport/cronet/transport/cronet_transport.cc index 9b2ca6f091f..e1ff13d5dbe 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.cc +++ b/src/core/ext/transport/cronet/transport/cronet_transport.cc @@ -704,17 +704,8 @@ static void convert_metadata_to_cronet_headers( grpc_metadata_batch* metadata, const char* host, std::string* pp_url, bidirectional_stream_header** pp_headers, size_t* p_num_headers, const char** method) { - grpc_linked_mdelem* curr = metadata->list.head; - /* Walk the linked list and get number of header fields */ - size_t num_headers_available = 0; - while (curr != nullptr) { - curr = curr->next; - num_headers_available++; - } - grpc_millis deadline = metadata->deadline; - if (deadline != GRPC_MILLIS_INF_FUTURE) { - num_headers_available++; - } + /* Get number of header fields */ + size_t num_headers_available = (*metadata)->count(); /* Allocate enough memory. It is freed in the on_stream_ready callback */ bidirectional_stream_header* headers = @@ -727,11 +718,8 @@ static void convert_metadata_to_cronet_headers( are not used for cronet. TODO (makdharma): Eliminate need to traverse the LL second time for perf. */ - curr = metadata->list.head; size_t num_headers = 0; - while (num_headers < num_headers_available) { - grpc_mdelem mdelem = curr->md; - curr = curr->next; + (*metadata)->ForEach([&](grpc_mdelem mdelem) { char* key = grpc_slice_to_c_string(GRPC_MDKEY(mdelem)); char* value; if (grpc_is_binary_header_internal(GRPC_MDKEY(mdelem))) { @@ -747,7 +735,7 @@ static void convert_metadata_to_cronet_headers( /* Cronet populates these fields on its own */ gpr_free(key); gpr_free(value); - continue; + return; } if (grpc_slice_eq_static_interned(GRPC_MDKEY(mdelem), GRPC_MDSTR_METHOD)) { if (grpc_slice_eq_static_interned(GRPC_MDVALUE(mdelem), GRPC_MDSTR_PUT)) { @@ -758,29 +746,26 @@ static void convert_metadata_to_cronet_headers( } gpr_free(key); gpr_free(value); - continue; + return; } if (grpc_slice_eq_static_interned(GRPC_MDKEY(mdelem), GRPC_MDSTR_PATH)) { /* Create URL by appending :path value to the hostname */ *pp_url = absl::StrCat("https://", host, value); gpr_free(key); gpr_free(value); - continue; + return; } CRONET_LOG(GPR_DEBUG, "header %s = %s", key, value); headers[num_headers].key = key; headers[num_headers].value = value; num_headers++; - if (curr == nullptr) { - break; - } - } - if (deadline != GRPC_MILLIS_INF_FUTURE) { + }); + if ((*metadata)->deadline() != GRPC_MILLIS_INF_FUTURE) { char* key = grpc_slice_to_c_string(GRPC_MDSTR_GRPC_TIMEOUT); char* value = static_cast(gpr_malloc(GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE)); - grpc_http2_encode_timeout(deadline - grpc_core::ExecCtx::Get()->Now(), - value); + grpc_http2_encode_timeout( + (*metadata)->deadline() - grpc_core::ExecCtx::Get()->Now(), value); headers[num_headers].key = key; headers[num_headers].value = value; @@ -802,15 +787,14 @@ static void parse_grpc_header(const uint8_t* data, int* length, *length |= (*p++); } -static bool header_has_authority(grpc_linked_mdelem* head) { - while (head != nullptr) { - if (grpc_slice_eq_static_interned(GRPC_MDKEY(head->md), - GRPC_MDSTR_AUTHORITY)) { - return true; +static bool header_has_authority(const grpc_metadata_batch* b) { + bool found = false; + (*b)->ForEach([&](grpc_mdelem elem) { + if (grpc_slice_eq_static_interned(GRPC_MDKEY(elem), GRPC_MDSTR_AUTHORITY)) { + found = true; } - head = head->next; - } - return false; + }); + return found; } /* @@ -1438,8 +1422,8 @@ static void perform_stream_op(grpc_transport* /*gt*/, grpc_stream* gs, grpc_transport_stream_op_batch* op) { CRONET_LOG(GPR_DEBUG, "perform_stream_op"); if (op->send_initial_metadata && - header_has_authority(op->payload->send_initial_metadata - .send_initial_metadata->list.head)) { + header_has_authority( + op->payload->send_initial_metadata.send_initial_metadata)) { /* Cronet does not support :authority header field. We cancel the call when this field is present in metadata */ if (op->recv_initial_metadata) { diff --git a/src/core/ext/transport/inproc/inproc_transport.cc b/src/core/ext/transport/inproc/inproc_transport.cc index bbe62e5692d..e5737e230a0 100644 --- a/src/core/ext/transport/inproc/inproc_transport.cc +++ b/src/core/ext/transport/inproc/inproc_transport.cc @@ -285,15 +285,14 @@ struct inproc_stream { void log_metadata(const grpc_metadata_batch* md_batch, bool is_client, bool is_initial) { - for (grpc_linked_mdelem* md = md_batch->list.head; md != nullptr; - md = md->next) { - char* key = grpc_slice_to_c_string(GRPC_MDKEY(md->md)); - char* value = grpc_slice_to_c_string(GRPC_MDVALUE(md->md)); + (*md_batch)->ForEach([=](grpc_mdelem md) { + char* key = grpc_slice_to_c_string(GRPC_MDKEY(md)); + char* value = grpc_slice_to_c_string(GRPC_MDVALUE(md)); gpr_log(GPR_INFO, "INPROC:%s:%s: %s: %s", is_initial ? "HDR" : "TRL", is_client ? "CLI" : "SVR", key, value); gpr_free(key); gpr_free(value); - } + }); } grpc_error_handle fill_in_metadata(inproc_stream* s, @@ -311,16 +310,15 @@ grpc_error_handle fill_in_metadata(inproc_stream* s, *markfilled = true; } grpc_error_handle error = GRPC_ERROR_NONE; - for (grpc_linked_mdelem* elem = metadata->list.head; - (elem != nullptr) && (error == GRPC_ERROR_NONE); elem = elem->next) { + (*metadata)->ForEach([&](grpc_mdelem md) { + if (error != GRPC_ERROR_NONE) return; grpc_linked_mdelem* nelem = static_cast(s->arena->Alloc(sizeof(*nelem))); - nelem->md = - grpc_mdelem_from_slices(grpc_slice_intern(GRPC_MDKEY(elem->md)), - grpc_slice_intern(GRPC_MDVALUE(elem->md))); + nelem->md = grpc_mdelem_from_slices(grpc_slice_intern(GRPC_MDKEY(md)), + grpc_slice_intern(GRPC_MDVALUE(md))); error = grpc_metadata_batch_link_tail(out_md, nelem); - } + }); return error; } @@ -709,8 +707,9 @@ void op_state_machine_locked(inproc_stream* s, grpc_error_handle error) { .recv_initial_metadata, s->recv_initial_md_op->payload->recv_initial_metadata.recv_flags, nullptr); - s->recv_initial_md_op->payload->recv_initial_metadata - .recv_initial_metadata->deadline = s->deadline; + (*s->recv_initial_md_op->payload->recv_initial_metadata + .recv_initial_metadata) + ->SetDeadline(s->deadline); if (s->recv_initial_md_op->payload->recv_initial_metadata .trailing_metadata_available != nullptr) { *s->recv_initial_md_op->payload->recv_initial_metadata @@ -1033,8 +1032,9 @@ void perform_stream_op(grpc_transport* gt, grpc_stream* gs, if (s->t->is_client) { grpc_millis* dl = (other == nullptr) ? &s->write_buffer_deadline : &other->deadline; - *dl = GPR_MIN(*dl, op->payload->send_initial_metadata - .send_initial_metadata->deadline); + *dl = GPR_MIN( + *dl, (*op->payload->send_initial_metadata.send_initial_metadata) + ->deadline()); s->initial_md_sent = true; } } diff --git a/src/core/lib/security/authorization/evaluate_args.cc b/src/core/lib/security/authorization/evaluate_args.cc index aa9f249489a..05f9cf9d825 100644 --- a/src/core/lib/security/authorization/evaluate_args.cc +++ b/src/core/lib/security/authorization/evaluate_args.cc @@ -80,8 +80,9 @@ EvaluateArgs::PerChannelArgs::PerChannelArgs(grpc_auth_context* auth_context, absl::string_view EvaluateArgs::GetPath() const { absl::string_view path; - if (metadata_ != nullptr && metadata_->idx.named.path != nullptr) { - grpc_linked_mdelem* elem = metadata_->idx.named.path; + if (metadata_ != nullptr && + (*metadata_)->legacy_index()->named.path != nullptr) { + grpc_linked_mdelem* elem = (*metadata_)->legacy_index()->named.path; const grpc_slice& val = GRPC_MDVALUE(elem->md); path = StringViewFromSlice(val); } @@ -90,8 +91,9 @@ absl::string_view EvaluateArgs::GetPath() const { absl::string_view EvaluateArgs::GetHost() const { absl::string_view host; - if (metadata_ != nullptr && metadata_->idx.named.host != nullptr) { - grpc_linked_mdelem* elem = metadata_->idx.named.host; + if (metadata_ != nullptr && + (*metadata_)->legacy_index()->named.host != nullptr) { + grpc_linked_mdelem* elem = (*metadata_)->legacy_index()->named.host; const grpc_slice& val = GRPC_MDVALUE(elem->md); host = StringViewFromSlice(val); } @@ -100,8 +102,9 @@ absl::string_view EvaluateArgs::GetHost() const { absl::string_view EvaluateArgs::GetMethod() const { absl::string_view method; - if (metadata_ != nullptr && metadata_->idx.named.method != nullptr) { - grpc_linked_mdelem* elem = metadata_->idx.named.method; + if (metadata_ != nullptr && + (*metadata_)->legacy_index()->named.method != nullptr) { + grpc_linked_mdelem* elem = (*metadata_)->legacy_index()->named.method; const grpc_slice& val = GRPC_MDVALUE(elem->md); method = StringViewFromSlice(val); } @@ -114,12 +117,11 @@ std::multimap EvaluateArgs::GetHeaders() if (metadata_ == nullptr) { return headers; } - for (grpc_linked_mdelem* elem = metadata_->list.head; elem != nullptr; - elem = elem->next) { - const grpc_slice& key = GRPC_MDKEY(elem->md); - const grpc_slice& val = GRPC_MDVALUE(elem->md); + (*metadata_)->ForEach([&](grpc_mdelem md) { + const grpc_slice& key = GRPC_MDKEY(md); + const grpc_slice& val = GRPC_MDVALUE(md); headers.emplace(StringViewFromSlice(key), StringViewFromSlice(val)); - } + }); return headers; } diff --git a/src/core/lib/security/transport/client_auth_filter.cc b/src/core/lib/security/transport/client_auth_filter.cc index 4e940b170e9..b3eada840f1 100644 --- a/src/core/lib/security/transport/client_auth_filter.cc +++ b/src/core/lib/security/transport/client_auth_filter.cc @@ -372,13 +372,13 @@ static void client_auth_start_transport_stream_op_batch( if (batch->send_initial_metadata) { grpc_metadata_batch* metadata = batch->payload->send_initial_metadata.send_initial_metadata; - if (metadata->idx.named.path != nullptr) { - calld->method = - grpc_slice_ref_internal(GRPC_MDVALUE(metadata->idx.named.path->md)); + if ((*metadata)->legacy_index()->named.path != nullptr) { + calld->method = grpc_slice_ref_internal( + GRPC_MDVALUE((*metadata)->legacy_index()->named.path->md)); } - if (metadata->idx.named.authority != nullptr) { + if ((*metadata)->legacy_index()->named.authority != nullptr) { calld->host = grpc_slice_ref_internal( - GRPC_MDVALUE(metadata->idx.named.authority->md)); + GRPC_MDVALUE((*metadata)->legacy_index()->named.authority->md)); batch->handler_private.extra_arg = elem; GRPC_CALL_STACK_REF(calld->owning_call, "check_call_host"); GRPC_CLOSURE_INIT(&calld->async_result_closure, on_host_checked, batch, diff --git a/src/core/lib/security/transport/server_auth_filter.cc b/src/core/lib/security/transport/server_auth_filter.cc index 4e9defd9711..000a3610444 100644 --- a/src/core/lib/security/transport/server_auth_filter.cc +++ b/src/core/lib/security/transport/server_auth_filter.cc @@ -96,12 +96,10 @@ struct call_data { static grpc_metadata_array metadata_batch_to_md_array( const grpc_metadata_batch* batch) { - grpc_linked_mdelem* l; grpc_metadata_array result; grpc_metadata_array_init(&result); - for (l = batch->list.head; l != nullptr; l = l->next) { + (*batch)->ForEach([&](grpc_mdelem md) { grpc_metadata* usr_md = nullptr; - grpc_mdelem md = l->md; grpc_slice key = GRPC_MDKEY(md); grpc_slice value = GRPC_MDVALUE(md); if (result.count == result.capacity) { @@ -112,7 +110,7 @@ static grpc_metadata_array metadata_batch_to_md_array( usr_md = &result.metadata[result.count++]; usr_md->key = grpc_slice_ref_internal(key); usr_md->value = grpc_slice_ref_internal(value); - } + }); return result; } diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 5d91002228f..36a52d07b17 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -146,7 +146,7 @@ struct grpc_call { stream_op_payload(context) { for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { - metadata_batch[i][j].deadline = GRPC_MILLIS_INF_FUTURE; + metadata_batch[i][j]->ClearDeadline(); } } } @@ -1000,52 +1000,56 @@ static grpc_stream_compression_algorithm decode_stream_compression( static void publish_app_metadata(grpc_call* call, grpc_metadata_batch* b, int is_trailing) { - if (b->list.count == 0) return; + if ((*b)->non_deadline_count() == 0) return; if (!call->is_client && is_trailing) return; if (is_trailing && call->buffered_metadata[1] == nullptr) return; GPR_TIMER_SCOPE("publish_app_metadata", 0); grpc_metadata_array* dest; grpc_metadata* mdusr; dest = call->buffered_metadata[is_trailing]; - if (dest->count + b->list.count > dest->capacity) { - dest->capacity = - GPR_MAX(dest->capacity + b->list.count, dest->capacity * 3 / 2); + if (dest->count + (*b)->non_deadline_count() > dest->capacity) { + dest->capacity = GPR_MAX(dest->capacity + (*b)->non_deadline_count(), + dest->capacity * 3 / 2); dest->metadata = static_cast( gpr_realloc(dest->metadata, sizeof(grpc_metadata) * dest->capacity)); } - for (grpc_linked_mdelem* l = b->list.head; l != nullptr; l = l->next) { + (*b)->ForEach([&](grpc_mdelem md) { mdusr = &dest->metadata[dest->count++]; /* we pass back borrowed slices that are valid whilst the call is valid */ - mdusr->key = GRPC_MDKEY(l->md); - mdusr->value = GRPC_MDVALUE(l->md); - } + mdusr->key = GRPC_MDKEY(md); + mdusr->value = GRPC_MDVALUE(md); + }); } static void recv_initial_filter(grpc_call* call, grpc_metadata_batch* b) { - if (b->idx.named.content_encoding != nullptr) { + if ((*b)->legacy_index()->named.content_encoding != nullptr) { GPR_TIMER_SCOPE("incoming_stream_compression_algorithm", 0); set_incoming_stream_compression_algorithm( - call, decode_stream_compression(b->idx.named.content_encoding->md)); + call, decode_stream_compression( + (*b)->legacy_index()->named.content_encoding->md)); grpc_metadata_batch_remove(b, GRPC_BATCH_CONTENT_ENCODING); } - if (b->idx.named.grpc_encoding != nullptr) { + if ((*b)->legacy_index()->named.grpc_encoding != nullptr) { GPR_TIMER_SCOPE("incoming_message_compression_algorithm", 0); set_incoming_message_compression_algorithm( - call, decode_message_compression(b->idx.named.grpc_encoding->md)); + call, decode_message_compression( + (*b)->legacy_index()->named.grpc_encoding->md)); grpc_metadata_batch_remove(b, GRPC_BATCH_GRPC_ENCODING); } uint32_t message_encodings_accepted_by_peer = 1u; uint32_t stream_encodings_accepted_by_peer = 1u; - if (b->idx.named.grpc_accept_encoding != nullptr) { + if ((*b)->legacy_index()->named.grpc_accept_encoding != nullptr) { GPR_TIMER_SCOPE("encodings_accepted_by_peer", 0); - set_encodings_accepted_by_peer(call, b->idx.named.grpc_accept_encoding->md, - &message_encodings_accepted_by_peer, false); + set_encodings_accepted_by_peer( + call, (*b)->legacy_index()->named.grpc_accept_encoding->md, + &message_encodings_accepted_by_peer, false); grpc_metadata_batch_remove(b, GRPC_BATCH_GRPC_ACCEPT_ENCODING); } - if (b->idx.named.accept_encoding != nullptr) { + if ((*b)->legacy_index()->named.accept_encoding != nullptr) { GPR_TIMER_SCOPE("stream_encodings_accepted_by_peer", 0); - set_encodings_accepted_by_peer(call, b->idx.named.accept_encoding->md, - &stream_encodings_accepted_by_peer, true); + set_encodings_accepted_by_peer( + call, (*b)->legacy_index()->named.accept_encoding->md, + &stream_encodings_accepted_by_peer, true); grpc_metadata_batch_remove(b, GRPC_BATCH_ACCEPT_ENCODING); } call->encodings_accepted_by_peer = @@ -1060,9 +1064,9 @@ static void recv_trailing_filter(void* args, grpc_metadata_batch* b, grpc_call* call = static_cast(args); if (batch_error != GRPC_ERROR_NONE) { set_final_status(call, batch_error); - } else if (b->idx.named.grpc_status != nullptr) { - grpc_status_code status_code = - grpc_get_status_code_from_metadata(b->idx.named.grpc_status->md); + } else if ((*b)->legacy_index()->named.grpc_status != nullptr) { + grpc_status_code status_code = grpc_get_status_code_from_metadata( + (*b)->legacy_index()->named.grpc_status->md); grpc_error_handle error = GRPC_ERROR_NONE; if (status_code != GRPC_STATUS_OK) { char* peer = grpc_call_get_peer(call); @@ -1072,10 +1076,11 @@ static void recv_trailing_filter(void* args, grpc_metadata_batch* b, static_cast(status_code)); gpr_free(peer); } - if (b->idx.named.grpc_message != nullptr) { + if ((*b)->legacy_index()->named.grpc_message != nullptr) { error = grpc_error_set_str( error, GRPC_ERROR_STR_GRPC_MESSAGE, - grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.grpc_message->md))); + grpc_slice_ref_internal( + GRPC_MDVALUE((*b)->legacy_index()->named.grpc_message->md))); grpc_metadata_batch_remove(b, GRPC_BATCH_GRPC_MESSAGE); } else if (error != GRPC_ERROR_NONE) { error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, @@ -1483,8 +1488,9 @@ static void receiving_initial_metadata_ready(void* bctlp, GPR_TIMER_SCOPE("validate_filtered_metadata", 0); validate_filtered_metadata(bctl); - if (md->deadline != GRPC_MILLIS_INF_FUTURE && !call->is_client) { - call->send_deadline = md->deadline; + grpc_millis deadline = (*md)->deadline(); + if (deadline != GRPC_MILLIS_INF_FUTURE && !call->is_client) { + call->send_deadline = deadline; } } else { if (reinterpret_cast( @@ -1670,7 +1676,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, } /* TODO(ctiller): just make these the same variable? */ if (call->is_client) { - call->metadata_batch[0][0].deadline = call->send_deadline; + call->metadata_batch[0][0]->SetDeadline(call->send_deadline); } stream_op_payload->send_initial_metadata.send_initial_metadata = &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]; @@ -2025,8 +2031,8 @@ grpc_compression_algorithm grpc_call_compression_for_level( bool grpc_call_is_trailers_only(const grpc_call* call) { bool result = call->is_trailers_only; GPR_DEBUG_ASSERT( - !result || call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */] - .list.count == 0); + !result || + call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */]->empty()); return result; } diff --git a/src/core/lib/surface/server.cc b/src/core/lib/surface/server.cc index 6c5f713bb26..752e53c2330 100644 --- a/src/core/lib/surface/server.cc +++ b/src/core/lib/surface/server.cc @@ -1381,20 +1381,25 @@ void Server::CallData::RecvInitialMetadataReady(void* arg, CallData* calld = static_cast(elem->call_data); grpc_millis op_deadline; if (error == GRPC_ERROR_NONE) { - GPR_DEBUG_ASSERT(calld->recv_initial_metadata_->idx.named.path != nullptr); - GPR_DEBUG_ASSERT(calld->recv_initial_metadata_->idx.named.authority != - nullptr); - calld->path_.emplace(grpc_slice_ref_internal( - GRPC_MDVALUE(calld->recv_initial_metadata_->idx.named.path->md))); - calld->host_.emplace(grpc_slice_ref_internal( - GRPC_MDVALUE(calld->recv_initial_metadata_->idx.named.authority->md))); + GPR_DEBUG_ASSERT( + (*calld->recv_initial_metadata_)->legacy_index()->named.path != + nullptr); + GPR_DEBUG_ASSERT( + (*calld->recv_initial_metadata_)->legacy_index()->named.authority != + nullptr); + calld->path_.emplace(grpc_slice_ref_internal(GRPC_MDVALUE( + (*calld->recv_initial_metadata_)->legacy_index()->named.path->md))); + calld->host_.emplace( + grpc_slice_ref_internal(GRPC_MDVALUE((*calld->recv_initial_metadata_) + ->legacy_index() + ->named.authority->md))); grpc_metadata_batch_remove(calld->recv_initial_metadata_, GRPC_BATCH_PATH); grpc_metadata_batch_remove(calld->recv_initial_metadata_, GRPC_BATCH_AUTHORITY); } else { GRPC_ERROR_REF(error); } - op_deadline = calld->recv_initial_metadata_->deadline; + op_deadline = (*calld->recv_initial_metadata_)->deadline(); if (op_deadline != GRPC_MILLIS_INF_FUTURE) { calld->deadline_ = op_deadline; } diff --git a/src/core/lib/transport/metadata_batch.cc b/src/core/lib/transport/metadata_batch.cc index 8207fb5ee56..79ea14a2e71 100644 --- a/src/core/lib/transport/metadata_batch.cc +++ b/src/core/lib/transport/metadata_batch.cc @@ -33,6 +33,8 @@ #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" +namespace grpc_core { + static void assert_valid_list(grpc_mdelem_list* list) { #ifndef NDEBUG grpc_linked_mdelem* l; @@ -59,48 +61,44 @@ static void assert_valid_list(grpc_mdelem_list* list) { #endif /* NDEBUG */ } -static void assert_valid_callouts(grpc_metadata_batch* batch) { +void MetadataMap::AssertValidCallouts() { #ifndef NDEBUG - for (grpc_linked_mdelem* l = batch->list.head; l != nullptr; l = l->next) { + for (grpc_linked_mdelem* l = list_.head; l != nullptr; l = l->next) { grpc_slice key_interned = grpc_slice_intern(GRPC_MDKEY(l->md)); grpc_metadata_batch_callouts_index callout_idx = GRPC_BATCH_INDEX_OF(key_interned); if (callout_idx != GRPC_BATCH_CALLOUTS_COUNT) { - GPR_ASSERT(batch->idx.array[callout_idx] == l); + GPR_ASSERT(idx_.array[callout_idx] == l); } grpc_slice_unref_internal(key_interned); } -#else - // Avoid unused-parameter warning for debug-only parameter - (void)batch; #endif } #ifndef NDEBUG -void grpc_metadata_batch_assert_ok(grpc_metadata_batch* batch) { - assert_valid_list(&batch->list); -} +void MetadataMap::AssertOk() { assert_valid_list(&list_); } #endif /* NDEBUG */ -void grpc_metadata_batch_init(grpc_metadata_batch* batch) { - memset(batch, 0, sizeof(*batch)); - batch->deadline = GRPC_MILLIS_INF_FUTURE; +MetadataMap::MetadataMap() { + memset(&list_, 0, sizeof(list_)); + memset(&idx_, 0, sizeof(idx_)); + deadline_ = GRPC_MILLIS_INF_FUTURE; } -void grpc_metadata_batch_destroy(grpc_metadata_batch* batch) { - grpc_linked_mdelem* l; - for (l = batch->list.head; l; l = l->next) { - GRPC_MDELEM_UNREF(l->md); - } +MetadataMap::MetadataMap(MetadataMap&& other) noexcept { + list_ = other.list_; + idx_ = other.idx_; + deadline_ = other.deadline_; + memset(&other.list_, 0, sizeof(list_)); + memset(&other.idx_, 0, sizeof(idx_)); + other.deadline_ = GRPC_MILLIS_INF_FUTURE; } -grpc_error_handle grpc_attach_md_to_error(grpc_error_handle src, - grpc_mdelem md) { - grpc_error_handle out = grpc_error_set_str( - grpc_error_set_str(src, GRPC_ERROR_STR_KEY, - grpc_slice_ref_internal(GRPC_MDKEY(md))), - GRPC_ERROR_STR_VALUE, grpc_slice_ref_internal(GRPC_MDVALUE(md))); - return out; +MetadataMap::~MetadataMap() { + AssertValidCallouts(); + for (auto* l = list_.head; l; l = l->next) { + GRPC_MDELEM_UNREF(l->md); + } } static grpc_error_handle GPR_ATTRIBUTE_NOINLINE error_with_md(grpc_mdelem md) { @@ -108,50 +106,56 @@ static grpc_error_handle GPR_ATTRIBUTE_NOINLINE error_with_md(grpc_mdelem md) { GRPC_ERROR_CREATE_FROM_STATIC_STRING("Unallowed duplicate metadata"), md); } -static grpc_error_handle link_callout(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage, - grpc_metadata_batch_callouts_index idx) { +absl::optional MetadataMap::Remove(grpc_slice key) { + for (auto* l = list_.head; l; l = l->next) { + if (grpc_slice_eq(GRPC_MDKEY(l->md), key)) { + auto out = grpc_slice_ref_internal(GRPC_MDVALUE(l->md)); + Remove(l); + return out; + } + } + return {}; +} + +grpc_error_handle MetadataMap::LinkCallout( + grpc_linked_mdelem* storage, grpc_metadata_batch_callouts_index idx) { + AssertValidCallouts(); GPR_DEBUG_ASSERT(idx >= 0 && idx < GRPC_BATCH_CALLOUTS_COUNT); - if (GPR_LIKELY(batch->idx.array[idx] == nullptr)) { - ++batch->list.default_count; - batch->idx.array[idx] = storage; + if (GPR_LIKELY(idx_.array[idx] == nullptr)) { + ++list_.default_count; + idx_.array[idx] = storage; + AssertValidCallouts(); return GRPC_ERROR_NONE; } + AssertValidCallouts(); return error_with_md(storage->md); } -static grpc_error_handle maybe_link_callout(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage) - GRPC_MUST_USE_RESULT; - -static grpc_error_handle maybe_link_callout(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage) { +grpc_error_handle MetadataMap::MaybeLinkCallout(grpc_linked_mdelem* storage) { grpc_metadata_batch_callouts_index idx = GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)); if (idx == GRPC_BATCH_CALLOUTS_COUNT) { return GRPC_ERROR_NONE; } - return link_callout(batch, storage, idx); + return LinkCallout(storage, idx); } -static void maybe_unlink_callout(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage) { +void MetadataMap::MaybeUnlinkCallout(grpc_linked_mdelem* storage) { grpc_metadata_batch_callouts_index idx = GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)); if (idx == GRPC_BATCH_CALLOUTS_COUNT) { return; } - --batch->list.default_count; - GPR_DEBUG_ASSERT(batch->idx.array[idx] != nullptr); - batch->idx.array[idx] = nullptr; + --list_.default_count; + GPR_DEBUG_ASSERT(idx_.array[idx] != nullptr); + idx_.array[idx] = nullptr; } -grpc_error_handle grpc_metadata_batch_add_head(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage, - grpc_mdelem elem_to_add) { +grpc_error_handle MetadataMap::AddHead(grpc_linked_mdelem* storage, + grpc_mdelem elem_to_add) { GPR_DEBUG_ASSERT(!GRPC_MDISNULL(elem_to_add)); storage->md = elem_to_add; - return grpc_metadata_batch_link_head(batch, storage); + return LinkHead(storage); } static void link_head(grpc_mdelem_list* list, grpc_linked_mdelem* storage) { @@ -170,43 +174,40 @@ static void link_head(grpc_mdelem_list* list, grpc_linked_mdelem* storage) { assert_valid_list(list); } -grpc_error_handle grpc_metadata_batch_link_head(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage) { - assert_valid_callouts(batch); - grpc_error_handle err = maybe_link_callout(batch, storage); +grpc_error_handle MetadataMap::LinkHead(grpc_linked_mdelem* storage) { + AssertValidCallouts(); + grpc_error_handle err = MaybeLinkCallout(storage); if (err != GRPC_ERROR_NONE) { - assert_valid_callouts(batch); + AssertValidCallouts(); return err; } - link_head(&batch->list, storage); - assert_valid_callouts(batch); + link_head(&list_, storage); + AssertValidCallouts(); return GRPC_ERROR_NONE; } // TODO(arjunroy): Need to revisit this and see what guarantees exist between // C-core and the internal-metadata subsystem. E.g. can we ensure a particular // metadata is never added twice, even in the presence of user supplied data? -grpc_error_handle grpc_metadata_batch_link_head( - grpc_metadata_batch* batch, grpc_linked_mdelem* storage, - grpc_metadata_batch_callouts_index idx) { +grpc_error_handle MetadataMap::LinkHead( + grpc_linked_mdelem* storage, grpc_metadata_batch_callouts_index idx) { GPR_DEBUG_ASSERT(GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)) == idx); - assert_valid_callouts(batch); - grpc_error_handle err = link_callout(batch, storage, idx); + AssertValidCallouts(); + grpc_error_handle err = LinkCallout(storage, idx); if (GPR_UNLIKELY(err != GRPC_ERROR_NONE)) { - assert_valid_callouts(batch); + AssertValidCallouts(); return err; } - link_head(&batch->list, storage); - assert_valid_callouts(batch); + link_head(&list_, storage); + AssertValidCallouts(); return GRPC_ERROR_NONE; } -grpc_error_handle grpc_metadata_batch_add_tail(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage, - grpc_mdelem elem_to_add) { +grpc_error_handle MetadataMap::AddTail(grpc_linked_mdelem* storage, + grpc_mdelem elem_to_add) { GPR_DEBUG_ASSERT(!GRPC_MDISNULL(elem_to_add)); storage->md = elem_to_add; - return grpc_metadata_batch_link_tail(batch, storage); + return LinkTail(storage); } static void link_tail(grpc_mdelem_list* list, grpc_linked_mdelem* storage) { @@ -225,31 +226,29 @@ static void link_tail(grpc_mdelem_list* list, grpc_linked_mdelem* storage) { assert_valid_list(list); } -grpc_error_handle grpc_metadata_batch_link_tail(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage) { - assert_valid_callouts(batch); - grpc_error_handle err = maybe_link_callout(batch, storage); +grpc_error_handle MetadataMap::LinkTail(grpc_linked_mdelem* storage) { + AssertValidCallouts(); + grpc_error_handle err = MaybeLinkCallout(storage); if (err != GRPC_ERROR_NONE) { - assert_valid_callouts(batch); + AssertValidCallouts(); return err; } - link_tail(&batch->list, storage); - assert_valid_callouts(batch); + link_tail(&list_, storage); + AssertValidCallouts(); return GRPC_ERROR_NONE; } -grpc_error_handle grpc_metadata_batch_link_tail( - grpc_metadata_batch* batch, grpc_linked_mdelem* storage, - grpc_metadata_batch_callouts_index idx) { +grpc_error_handle MetadataMap::LinkTail( + grpc_linked_mdelem* storage, grpc_metadata_batch_callouts_index idx) { GPR_DEBUG_ASSERT(GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)) == idx); - assert_valid_callouts(batch); - grpc_error_handle err = link_callout(batch, storage, idx); + AssertValidCallouts(); + grpc_error_handle err = LinkCallout(storage, idx); if (GPR_UNLIKELY(err != GRPC_ERROR_NONE)) { - assert_valid_callouts(batch); + AssertValidCallouts(); return err; } - link_tail(&batch->list, storage); - assert_valid_callouts(batch); + link_tail(&list_, storage); + AssertValidCallouts(); return GRPC_ERROR_NONE; } @@ -270,44 +269,29 @@ static void unlink_storage(grpc_mdelem_list* list, assert_valid_list(list); } -void grpc_metadata_batch_remove(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage) { - assert_valid_callouts(batch); - maybe_unlink_callout(batch, storage); - unlink_storage(&batch->list, storage); +void MetadataMap::Remove(grpc_linked_mdelem* storage) { + AssertValidCallouts(); + MaybeUnlinkCallout(storage); + unlink_storage(&list_, storage); GRPC_MDELEM_UNREF(storage->md); - assert_valid_callouts(batch); + AssertValidCallouts(); } -void grpc_metadata_batch_remove(grpc_metadata_batch* batch, - grpc_metadata_batch_callouts_index idx) { - assert_valid_callouts(batch); - grpc_linked_mdelem* storage = batch->idx.array[idx]; - GPR_DEBUG_ASSERT(storage != nullptr); - --batch->list.default_count; - batch->idx.array[idx] = nullptr; - unlink_storage(&batch->list, storage); - GRPC_MDELEM_UNREF(storage->md); - assert_valid_callouts(batch); +void MetadataMap::Remove(grpc_metadata_batch_callouts_index idx) { + AssertValidCallouts(); + if (idx_.array[idx] == nullptr) return; + --list_.default_count; + unlink_storage(&list_, idx_.array[idx]); + GRPC_MDELEM_UNREF(idx_.array[idx]->md); + idx_.array[idx] = nullptr; + AssertValidCallouts(); } -void grpc_metadata_batch_set_value(grpc_linked_mdelem* storage, - const grpc_slice& value) { - grpc_mdelem old_mdelem = storage->md; - grpc_mdelem new_mdelem = grpc_mdelem_from_slices( - grpc_slice_ref_internal(GRPC_MDKEY(old_mdelem)), value); - storage->md = new_mdelem; - GRPC_MDELEM_UNREF(old_mdelem); -} - -absl::optional grpc_metadata_batch_get_value( - grpc_metadata_batch* batch, absl::string_view target_key, - std::string* concatenated_value) { +absl::optional MetadataMap::GetValue( + absl::string_view target_key, std::string* concatenated_value) const { // Find all values for the specified key. - GPR_DEBUG_ASSERT(batch != nullptr); absl::InlinedVector values; - for (grpc_linked_mdelem* md = batch->list.head; md != nullptr; - md = md->next) { + for (grpc_linked_mdelem* md = list_.head; md != nullptr; md = md->next) { absl::string_view key = grpc_core::StringViewFromSlice(GRPC_MDKEY(md->md)); absl::string_view value = grpc_core::StringViewFromSlice(GRPC_MDVALUE(md->md)); @@ -324,93 +308,83 @@ absl::optional grpc_metadata_batch_get_value( return *concatenated_value; } -grpc_error_handle grpc_metadata_batch_substitute(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage, - grpc_mdelem new_mdelem) { - assert_valid_callouts(batch); +grpc_error_handle MetadataMap::Substitute(grpc_linked_mdelem* storage, + grpc_mdelem new_mdelem) { + AssertValidCallouts(); grpc_error_handle error = GRPC_ERROR_NONE; grpc_mdelem old_mdelem = storage->md; if (!grpc_slice_eq(GRPC_MDKEY(new_mdelem), GRPC_MDKEY(old_mdelem))) { - maybe_unlink_callout(batch, storage); + MaybeUnlinkCallout(storage); storage->md = new_mdelem; - error = maybe_link_callout(batch, storage); + error = MaybeLinkCallout(storage); if (error != GRPC_ERROR_NONE) { - unlink_storage(&batch->list, storage); + unlink_storage(&list_, storage); GRPC_MDELEM_UNREF(storage->md); } } else { storage->md = new_mdelem; } GRPC_MDELEM_UNREF(old_mdelem); - assert_valid_callouts(batch); + AssertValidCallouts(); return error; } -void grpc_metadata_batch_clear(grpc_metadata_batch* batch) { - grpc_metadata_batch_destroy(batch); - grpc_metadata_batch_init(batch); +void MetadataMap::Clear() { + this->~MetadataMap(); + new (this) MetadataMap(); } -bool grpc_metadata_batch_is_empty(grpc_metadata_batch* batch) { - return batch->list.head == nullptr && - batch->deadline == GRPC_MILLIS_INF_FUTURE; -} - -size_t grpc_metadata_batch_size(grpc_metadata_batch* batch) { +size_t MetadataMap::TransportSize() const { size_t size = 0; - for (grpc_linked_mdelem* elem = batch->list.head; elem != nullptr; + for (grpc_linked_mdelem* elem = list_.head; elem != nullptr; elem = elem->next) { size += GRPC_MDELEM_LENGTH(elem->md); } return size; } -static void add_error(grpc_error_handle* composite, grpc_error_handle error, - const char* composite_error_string) { - if (error == GRPC_ERROR_NONE) return; - if (*composite == GRPC_ERROR_NONE) { - *composite = GRPC_ERROR_CREATE_FROM_COPIED_STRING(composite_error_string); +bool MetadataMap::ReplaceIfExists(grpc_slice key, grpc_slice value) { + AssertValidCallouts(); + for (grpc_linked_mdelem* l = list_.head; l != nullptr; l = l->next) { + if (grpc_slice_eq(GRPC_MDKEY(l->md), key)) { + auto new_mdelem = grpc_mdelem_from_slices(grpc_slice_ref_internal(key), + grpc_slice_ref_internal(value)); + GRPC_MDELEM_UNREF(l->md); + l->md = new_mdelem; + AssertValidCallouts(); + return true; + } } - *composite = grpc_error_add_child(*composite, error); + AssertValidCallouts(); + return false; } -grpc_error_handle grpc_metadata_batch_filter( - grpc_metadata_batch* batch, grpc_metadata_batch_filter_func func, - void* user_data, const char* composite_error_string) { - grpc_linked_mdelem* l = batch->list.head; - grpc_error_handle error = GRPC_ERROR_NONE; - while (l) { - grpc_linked_mdelem* next = l->next; - grpc_filtered_mdelem new_mdelem = func(user_data, l->md); - add_error(&error, new_mdelem.error, composite_error_string); - if (GRPC_MDISNULL(new_mdelem.md)) { - grpc_metadata_batch_remove(batch, l); - } else if (new_mdelem.md.payload != l->md.payload) { - grpc_metadata_batch_substitute(batch, l, new_mdelem.md); - } - l = next; - } - return error; +} // namespace grpc_core + +void grpc_metadata_batch_set_value(grpc_linked_mdelem* storage, + const grpc_slice& value) { + grpc_mdelem old_mdelem = storage->md; + grpc_mdelem new_mdelem = grpc_mdelem_from_slices( + grpc_slice_ref_internal(GRPC_MDKEY(old_mdelem)), value); + storage->md = new_mdelem; + GRPC_MDELEM_UNREF(old_mdelem); } void grpc_metadata_batch_copy(grpc_metadata_batch* src, grpc_metadata_batch* dst, grpc_linked_mdelem* storage) { grpc_metadata_batch_init(dst); - dst->deadline = src->deadline; + (*dst)->SetDeadline((*src)->deadline()); size_t i = 0; - for (grpc_linked_mdelem* elem = src->list.head; elem != nullptr; - elem = elem->next) { + (*src)->ForEach([&](grpc_mdelem md) { // If the mdelem is not external, take a ref. // Otherwise, create a new copy, holding its own refs to the // underlying slices. - grpc_mdelem md; - if (GRPC_MDELEM_STORAGE(elem->md) != GRPC_MDELEM_STORAGE_EXTERNAL) { - md = GRPC_MDELEM_REF(elem->md); + if (GRPC_MDELEM_STORAGE(md) != GRPC_MDELEM_STORAGE_EXTERNAL) { + md = GRPC_MDELEM_REF(md); } else { - md = grpc_mdelem_from_slices( - grpc_slice_ref_internal(GRPC_MDKEY(elem->md)), - grpc_slice_ref_internal(GRPC_MDVALUE(elem->md))); + md = grpc_mdelem_from_slices(grpc_slice_ref_internal(GRPC_MDKEY(md)), + grpc_slice_ref_internal(GRPC_MDVALUE(md))); } // Error unused in non-debug builds. grpc_error_handle GRPC_UNUSED error = @@ -420,11 +394,14 @@ void grpc_metadata_batch_copy(grpc_metadata_batch* src, // the case here, because we would not have been allowed to create // a source batch that had that kind of conflict. GPR_DEBUG_ASSERT(error == GRPC_ERROR_NONE); - } + }); } -void grpc_metadata_batch_move(grpc_metadata_batch* src, - grpc_metadata_batch* dst) { - *dst = *src; - grpc_metadata_batch_init(src); +grpc_error_handle grpc_attach_md_to_error(grpc_error_handle src, + grpc_mdelem md) { + grpc_error_handle out = grpc_error_set_str( + grpc_error_set_str(src, GRPC_ERROR_STR_KEY, + grpc_slice_ref_internal(GRPC_MDKEY(md))), + GRPC_ERROR_STR_VALUE, grpc_slice_ref_internal(GRPC_MDVALUE(md))); + return out; } diff --git a/src/core/lib/transport/metadata_batch.h b/src/core/lib/transport/metadata_batch.h index 028bf527fa1..1405b5a3bf8 100644 --- a/src/core/lib/transport/metadata_batch.h +++ b/src/core/lib/transport/metadata_batch.h @@ -49,42 +49,190 @@ typedef struct grpc_mdelem_list { grpc_linked_mdelem* tail; } grpc_mdelem_list; -typedef struct grpc_metadata_batch { - /** Metadata elements in this batch */ - grpc_mdelem_list list; - grpc_metadata_batch_callouts idx; - /** Used to calculate grpc-timeout at the point of sending, - or GRPC_MILLIS_INF_FUTURE if this batch does not need to send a - grpc-timeout */ - grpc_millis deadline; +struct grpc_filtered_mdelem { + grpc_error_handle error; + grpc_mdelem md; +}; +#define GRPC_FILTERED_ERROR(error) \ + { (error), GRPC_MDNULL } +#define GRPC_FILTERED_MDELEM(md) \ + { GRPC_ERROR_NONE, (md) } +#define GRPC_FILTERED_REMOVE() \ + { GRPC_ERROR_NONE, GRPC_MDNULL } + +namespace grpc_core { + +// MetadataMap encodes the mapping of metadata keys to metadata values. +// Right now the API presented is the minimal one that will allow us to +// substitute this type for grpc_metadata_batch in a relatively easy fashion. At +// that point we'll start iterating this API into something that's ergonomic +// again, whilst minimally holding the performance bar already set (and +// hopefully improving some things). +// In the meantime, we're not going to invest much time in ephemeral API +// documentation, so if you must use one of these API's and it's not obvious +// how, reach out to ctiller. +class MetadataMap { + public: + MetadataMap(); + ~MetadataMap(); + + MetadataMap(const MetadataMap&) = delete; + MetadataMap& operator=(const MetadataMap&) = delete; + MetadataMap(MetadataMap&&) noexcept; + MetadataMap& operator=(MetadataMap&&) noexcept; template void Encode(Encoder* encoder) const { - for (auto* l = list.head; l; l = l->next) { + for (auto* l = list_.head; l; l = l->next) { encoder->Encode(l->md); } - if (deadline != GRPC_MILLIS_INF_FUTURE) encoder->EncodeDeadline(deadline); + if (deadline_ != GRPC_MILLIS_INF_FUTURE) encoder->EncodeDeadline(deadline_); } -} grpc_metadata_batch; -void grpc_metadata_batch_init(grpc_metadata_batch* batch); -void grpc_metadata_batch_destroy(grpc_metadata_batch* batch); -void grpc_metadata_batch_clear(grpc_metadata_batch* batch); -bool grpc_metadata_batch_is_empty(grpc_metadata_batch* batch); + template + void ForEach(F f) const { + for (auto* l = list_.head; l; l = l->next) { + f(l->md); + } + } + + template + grpc_error_handle Filter(F f, const char* composite_error_string) { + grpc_linked_mdelem* l = list_.head; + grpc_error_handle error = GRPC_ERROR_NONE; + auto add_error = [&](grpc_error_handle new_error) { + if (new_error == GRPC_ERROR_NONE) return; + if (error == GRPC_ERROR_NONE) { + error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(composite_error_string); + } + error = grpc_error_add_child(error, new_error); + }; + while (l) { + grpc_linked_mdelem* next = l->next; + grpc_filtered_mdelem new_mdelem = f(l->md); + add_error(new_mdelem.error); + if (GRPC_MDISNULL(new_mdelem.md)) { + Remove(l); + } else if (new_mdelem.md.payload != l->md.payload) { + Substitute(l, new_mdelem.md); + } + l = next; + } + return error; + } + + // Set key to value if it exists and return true, otherwise return false. + bool ReplaceIfExists(grpc_slice key, grpc_slice value); + + void Clear(); + bool empty() const { return count() == 0; } + + size_t count() const { + return list_.count + (deadline_ == GRPC_MILLIS_INF_FUTURE ? 0 : 1); + } + size_t non_deadline_count() const { return list_.count; } + size_t default_count() const { return list_.default_count; } + + size_t TransportSize() const; + + void Remove(grpc_linked_mdelem* storage); + void Remove(grpc_metadata_batch_callouts_index idx); + + absl::optional Remove(grpc_slice key); + + grpc_error_handle Substitute(grpc_linked_mdelem* storage, + grpc_mdelem new_mdelem); + + absl::optional GetValue( + absl::string_view target_key, std::string* concatenated_value) const; + + grpc_error_handle LinkHead(grpc_linked_mdelem* storage) GRPC_MUST_USE_RESULT; + grpc_error_handle LinkHead(grpc_linked_mdelem* storage, + grpc_metadata_batch_callouts_index idx) + GRPC_MUST_USE_RESULT; + grpc_error_handle LinkTail(grpc_linked_mdelem* storage) GRPC_MUST_USE_RESULT; + grpc_error_handle LinkTail(grpc_linked_mdelem* storage, + grpc_metadata_batch_callouts_index idx) + GRPC_MUST_USE_RESULT; + + grpc_error_handle AddHead(grpc_linked_mdelem* storage) GRPC_MUST_USE_RESULT; + grpc_error_handle AddHead(grpc_linked_mdelem* storage, + grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT; + grpc_error_handle AddTail(grpc_linked_mdelem* storage) GRPC_MUST_USE_RESULT; + grpc_error_handle AddTail(grpc_linked_mdelem* storage, + grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT; + + void CopyFrom(MetadataMap* src, grpc_linked_mdelem* storage); + +#ifndef NDEBUG + void AssertOk(); +#else + void AssertOk() {} +#endif + + grpc_millis deadline() const { return deadline_; } + void SetDeadline(grpc_millis deadline) { deadline_ = deadline; } + void ClearDeadline() { SetDeadline(GRPC_MILLIS_INF_FUTURE); } + + const grpc_metadata_batch_callouts* legacy_index() const { return &idx_; } + + private: + void AssertValidCallouts(); + grpc_error_handle LinkCallout(grpc_linked_mdelem* storage, + grpc_metadata_batch_callouts_index idx) + GRPC_MUST_USE_RESULT; + grpc_error_handle MaybeLinkCallout(grpc_linked_mdelem* storage) + GRPC_MUST_USE_RESULT; + void MaybeUnlinkCallout(grpc_linked_mdelem* storage); + + /** Metadata elements in this batch */ + grpc_mdelem_list list_; + grpc_metadata_batch_callouts idx_; + /** Used to calculate grpc-timeout at the point of sending, + or GRPC_MILLIS_INF_FUTURE if this batch does not need to send a + grpc-timeout */ + grpc_millis deadline_; +}; + +} // namespace grpc_core + +using grpc_metadata_batch = + grpc_core::ManualConstructor; + +inline void grpc_metadata_batch_init(grpc_metadata_batch* batch) { + batch->Init(); +} +inline void grpc_metadata_batch_destroy(grpc_metadata_batch* batch) { + batch->Destroy(); +} +inline void grpc_metadata_batch_clear(grpc_metadata_batch* batch) { + (*batch)->Clear(); +} +inline bool grpc_metadata_batch_is_empty(grpc_metadata_batch* batch) { + return (*batch)->empty(); +} /* Returns the transport size of the batch. */ -size_t grpc_metadata_batch_size(grpc_metadata_batch* batch); +inline size_t grpc_metadata_batch_size(grpc_metadata_batch* batch) { + return (*batch)->TransportSize(); +} /** Remove \a storage from the batch, unreffing the mdelem contained */ -void grpc_metadata_batch_remove(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage); -void grpc_metadata_batch_remove(grpc_metadata_batch* batch, - grpc_metadata_batch_callouts_index idx); +inline void grpc_metadata_batch_remove(grpc_metadata_batch* batch, + grpc_linked_mdelem* storage) { + (*batch)->Remove(storage); +} +inline void grpc_metadata_batch_remove(grpc_metadata_batch* batch, + grpc_metadata_batch_callouts_index idx) { + (*batch)->Remove(idx); +} /** Substitute a new mdelem for an old value */ -grpc_error_handle grpc_metadata_batch_substitute(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage, - grpc_mdelem new_mdelem); +inline grpc_error_handle grpc_metadata_batch_substitute( + grpc_metadata_batch* batch, grpc_linked_mdelem* storage, + grpc_mdelem new_mdelem) { + return (*batch)->Substitute(storage, new_mdelem); +} void grpc_metadata_batch_set_value(grpc_linked_mdelem* storage, const grpc_slice& value); @@ -96,33 +244,43 @@ void grpc_metadata_batch_set_value(grpc_linked_mdelem* storage, If the key is present more than once in the batch, constructs a comma-concatenated string of all values in concatenated_value and returns a string_view of that string. */ -absl::optional grpc_metadata_batch_get_value( +inline absl::optional grpc_metadata_batch_get_value( grpc_metadata_batch* batch, absl::string_view target_key, - std::string* concatenated_value); + std::string* concatenated_value) { + return (*batch)->GetValue(target_key, concatenated_value); +} /** Add \a storage to the beginning of \a batch. storage->md is assumed to be valid. \a storage is owned by the caller and must survive for the lifetime of batch. This usually means it should be around for the lifetime of the call. */ -grpc_error_handle grpc_metadata_batch_link_head(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage) - GRPC_MUST_USE_RESULT; -grpc_error_handle grpc_metadata_batch_link_head( +inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_link_head( + grpc_metadata_batch* batch, grpc_linked_mdelem* storage) { + return (*batch)->LinkHead(storage); +} + +inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_link_head( grpc_metadata_batch* batch, grpc_linked_mdelem* storage, - grpc_metadata_batch_callouts_index idx) GRPC_MUST_USE_RESULT; + grpc_metadata_batch_callouts_index idx) { + return (*batch)->LinkHead(storage, idx); +} /** Add \a storage to the end of \a batch. storage->md is assumed to be valid. \a storage is owned by the caller and must survive for the lifetime of batch. This usually means it should be around for the lifetime of the call. */ -grpc_error_handle grpc_metadata_batch_link_tail(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage) - GRPC_MUST_USE_RESULT; -grpc_error_handle grpc_metadata_batch_link_tail( +inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_link_tail( + grpc_metadata_batch* batch, grpc_linked_mdelem* storage) { + return (*batch)->LinkTail(storage); +} + +inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_link_tail( grpc_metadata_batch* batch, grpc_linked_mdelem* storage, - grpc_metadata_batch_callouts_index idx) GRPC_MUST_USE_RESULT; + grpc_metadata_batch_callouts_index idx) { + return (*batch)->LinkTail(storage, idx); +} /** Add \a elem_to_add as the first element in \a batch, using \a storage as backing storage for the linked list element. @@ -130,9 +288,11 @@ grpc_error_handle grpc_metadata_batch_link_tail( lifetime of batch. This usually means it should be around for the lifetime of the call. Takes ownership of \a elem_to_add */ -grpc_error_handle grpc_metadata_batch_add_head( +inline grpc_error_handle grpc_metadata_batch_add_head( grpc_metadata_batch* batch, grpc_linked_mdelem* storage, - grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT; + grpc_mdelem elem_to_add) { + return (*batch)->AddHead(storage, elem_to_add); +} // TODO(arjunroy, roth): Remove redundant methods. // add/link_head/tail are almost identical. @@ -156,9 +316,11 @@ inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_head( lifetime of batch. This usually means it should be around for the lifetime of the call. Takes ownership of \a elem_to_add */ -grpc_error_handle grpc_metadata_batch_add_tail( +inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_add_tail( grpc_metadata_batch* batch, grpc_linked_mdelem* storage, - grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT; + grpc_mdelem elem_to_add) { + return (*batch)->AddTail(storage, elem_to_add); +} inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_tail( grpc_metadata_batch* batch, grpc_linked_mdelem* storage, @@ -177,30 +339,19 @@ inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_tail( grpc_error_handle grpc_attach_md_to_error(grpc_error_handle src, grpc_mdelem md); -struct grpc_filtered_mdelem { - grpc_error_handle error; - grpc_mdelem md; -}; -#define GRPC_FILTERED_ERROR(error) \ - { (error), GRPC_MDNULL } -#define GRPC_FILTERED_MDELEM(md) \ - { GRPC_ERROR_NONE, (md) } -#define GRPC_FILTERED_REMOVE() \ - { GRPC_ERROR_NONE, GRPC_MDNULL } - typedef grpc_filtered_mdelem (*grpc_metadata_batch_filter_func)( void* user_data, grpc_mdelem elem); -grpc_error_handle grpc_metadata_batch_filter( +inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_filter( grpc_metadata_batch* batch, grpc_metadata_batch_filter_func func, - void* user_data, const char* composite_error_string) GRPC_MUST_USE_RESULT; + void* user_data, const char* composite_error_string) { + return (*batch)->Filter( + [=](grpc_mdelem elem) { return func(user_data, elem); }, + composite_error_string); +} -#ifndef NDEBUG -void grpc_metadata_batch_assert_ok(grpc_metadata_batch* batch); -#else -#define grpc_metadata_batch_assert_ok(batch) \ - do { \ - } while (0) -#endif +inline void grpc_metadata_batch_assert_ok(grpc_metadata_batch* batch) { + (*batch)->AssertOk(); +} /// Copies \a src to \a dst. \a storage must point to an array of /// \a grpc_linked_mdelem structs of at least the same size as \a src. @@ -215,7 +366,9 @@ void grpc_metadata_batch_copy(grpc_metadata_batch* src, grpc_metadata_batch* dst, grpc_linked_mdelem* storage); -void grpc_metadata_batch_move(grpc_metadata_batch* src, - grpc_metadata_batch* dst); +inline void grpc_metadata_batch_move(grpc_metadata_batch* src, + grpc_metadata_batch* dst) { + dst->Init(std::move(**src)); +} #endif /* GRPC_CORE_LIB_TRANSPORT_METADATA_BATCH_H */ diff --git a/src/core/lib/transport/transport_op_string.cc b/src/core/lib/transport/transport_op_string.cc index 449141d5db0..d17fb761dff 100644 --- a/src/core/lib/transport/transport_op_string.cc +++ b/src/core/lib/transport/transport_op_string.cc @@ -51,15 +51,16 @@ static void put_metadata(grpc_mdelem md, std::vector* out) { gpr_free(dump); } -static void put_metadata_list(grpc_metadata_batch md, +static void put_metadata_list(const grpc_metadata_batch& md, std::vector* out) { - grpc_linked_mdelem* m; - for (m = md.list.head; m != nullptr; m = m->next) { - if (m != md.list.head) out->push_back(", "); - put_metadata(m->md, out); - } - if (md.deadline != GRPC_MILLIS_INF_FUTURE) { - out->push_back(absl::StrFormat(" deadline=%" PRId64, md.deadline)); + bool first = true; + md->ForEach([&](grpc_mdelem elem) { + if (!first) out->push_back(", "); + first = false; + put_metadata(elem, out); + }); + if (md->deadline() != GRPC_MILLIS_INF_FUTURE) { + out->push_back(absl::StrFormat(" deadline=%" PRId64, md->deadline())); } } diff --git a/src/cpp/ext/filters/census/client_filter.cc b/src/cpp/ext/filters/census/client_filter.cc index bb332a889d8..fe1ec729a0d 100644 --- a/src/cpp/ext/filters/census/client_filter.cc +++ b/src/cpp/ext/filters/census/client_filter.cc @@ -123,13 +123,15 @@ void OpenCensusCallTracer::OpenCensusCallAttemptTracer::RecordReceivedMessage( namespace { void FilterTrailingMetadata(grpc_metadata_batch* b, uint64_t* elapsed_time) { - if (b->idx.named.grpc_server_stats_bin != nullptr) { + if ((*b)->legacy_index()->named.grpc_server_stats_bin != nullptr) { ServerStatsDeserialize( - reinterpret_cast(GRPC_SLICE_START_PTR( - GRPC_MDVALUE(b->idx.named.grpc_server_stats_bin->md))), - GRPC_SLICE_LENGTH(GRPC_MDVALUE(b->idx.named.grpc_server_stats_bin->md)), + reinterpret_cast(GRPC_SLICE_START_PTR(GRPC_MDVALUE( + (*b)->legacy_index()->named.grpc_server_stats_bin->md))), + GRPC_SLICE_LENGTH(GRPC_MDVALUE( + (*b)->legacy_index()->named.grpc_server_stats_bin->md)), elapsed_time); - grpc_metadata_batch_remove(b, b->idx.named.grpc_server_stats_bin); + grpc_metadata_batch_remove( + b, (*b)->legacy_index()->named.grpc_server_stats_bin); } } diff --git a/src/cpp/ext/filters/census/server_filter.cc b/src/cpp/ext/filters/census/server_filter.cc index fa606b80f65..0209bd2174d 100644 --- a/src/cpp/ext/filters/census/server_filter.cc +++ b/src/cpp/ext/filters/census/server_filter.cc @@ -45,17 +45,18 @@ struct ServerMetadataElements { void FilterInitialMetadata(grpc_metadata_batch* b, ServerMetadataElements* sml) { - if (b->idx.named.path != nullptr) { - sml->path = grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.path->md)); + if ((*b)->legacy_index()->named.path != nullptr) { + sml->path = grpc_slice_ref_internal( + GRPC_MDVALUE((*b)->legacy_index()->named.path->md)); } - if (b->idx.named.grpc_trace_bin != nullptr) { - sml->tracing_slice = - grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.grpc_trace_bin->md)); + if ((*b)->legacy_index()->named.grpc_trace_bin != nullptr) { + sml->tracing_slice = grpc_slice_ref_internal( + GRPC_MDVALUE((*b)->legacy_index()->named.grpc_trace_bin->md)); grpc_metadata_batch_remove(b, GRPC_BATCH_GRPC_TRACE_BIN); } - if (b->idx.named.grpc_tags_bin != nullptr) { - sml->census_proto = - grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.grpc_tags_bin->md)); + if ((*b)->legacy_index()->named.grpc_tags_bin != nullptr) { + sml->census_proto = grpc_slice_ref_internal( + GRPC_MDVALUE((*b)->legacy_index()->named.grpc_tags_bin->md)); grpc_metadata_batch_remove(b, GRPC_BATCH_GRPC_TAGS_BIN); } } diff --git a/test/core/end2end/tests/filter_status_code.cc b/test/core/end2end/tests/filter_status_code.cc index db9d5cbdd1d..d9965794f9f 100644 --- a/test/core/end2end/tests/filter_status_code.cc +++ b/test/core/end2end/tests/filter_status_code.cc @@ -263,9 +263,10 @@ static void server_start_transport_stream_op_batch( if (data->call == g_server_call_stack) { if (op->send_initial_metadata) { auto* batch = op->payload->send_initial_metadata.send_initial_metadata; - if (batch->idx.named.status != nullptr) { + if ((*batch)->legacy_index()->named.status != nullptr) { /* Replace the HTTP status with 404 */ - grpc_metadata_batch_substitute(batch, batch->idx.named.status, + grpc_metadata_batch_substitute(batch, + (*batch)->legacy_index()->named.status, GRPC_MDELEM_STATUS_404); } } diff --git a/test/core/transport/binder/binder_transport_test.cc b/test/core/transport/binder/binder_transport_test.cc index 56084bc8d1e..0d8b4577f6c 100644 --- a/test/core/transport/binder/binder_transport_test.cc +++ b/test/core/transport/binder/binder_transport_test.cc @@ -145,16 +145,16 @@ MATCHER_P(GrpcErrorMessageContains, msg, "") { // Verify that the lower-level metadata has the same content as the gRPC // metadata. -void VerifyMetadataEqual(const Metadata& md, grpc_metadata_batch grpc_md) { - grpc_linked_mdelem* elm = grpc_md.list.head; - for (size_t i = 0; i < md.size(); ++i) { - ASSERT_NE(elm, nullptr); - EXPECT_EQ(grpc_core::StringViewFromSlice(GRPC_MDKEY(elm->md)), md[i].first); - EXPECT_EQ(grpc_core::StringViewFromSlice(GRPC_MDVALUE(elm->md)), +void VerifyMetadataEqual(const Metadata& md, + const grpc_metadata_batch& grpc_md) { + size_t i = 0; + grpc_md->ForEach([&](grpc_mdelem mdelm) { + EXPECT_EQ(grpc_core::StringViewFromSlice(GRPC_MDKEY(mdelm)), md[i].first); + EXPECT_EQ(grpc_core::StringViewFromSlice(GRPC_MDVALUE(mdelm)), md[i].second); - elm = elm->next; - } - EXPECT_EQ(elm, nullptr); + i++; + }); + EXPECT_EQ(md.size(), i); } // RAII helper classes for constructing gRPC metadata and receiving callbacks. diff --git a/test/core/transport/chttp2/hpack_encoder_test.cc b/test/core/transport/chttp2/hpack_encoder_test.cc index e839c9ff0e2..e531dd30a4b 100644 --- a/test/core/transport/chttp2/hpack_encoder_test.cc +++ b/test/core/transport/chttp2/hpack_encoder_test.cc @@ -169,25 +169,16 @@ static void verify(const verify_params params, const char* expected, for (i = 0; i < nheaders; i++) { char* key = va_arg(l, char*); char* value = va_arg(l, char*); - if (i) { - e[i - 1].next = &e[i]; - e[i].prev = &e[i - 1]; - } grpc_slice value_slice = grpc_slice_from_static_string(value); if (!params.only_intern_key) { value_slice = grpc_slice_intern(value_slice); } e[i].md = grpc_mdelem_from_slices( grpc_slice_intern(grpc_slice_from_static_string(key)), value_slice); + GPR_ASSERT(GRPC_ERROR_NONE == b->LinkTail(&e[i])); } - e[0].prev = nullptr; - e[nheaders - 1].next = nullptr; va_end(l); - b.list.head = &e[0]; - b.list.tail = &e[nheaders - 1]; - b.list.count = nheaders; - if (cap_to_delete == num_to_delete) { cap_to_delete = GPR_MAX(2 * cap_to_delete, 1000); to_delete = static_cast( @@ -206,7 +197,7 @@ static void verify(const verify_params params, const char* expected, 16384, /* max_frame_size */ &stats /* stats */ }; - g_compressor->EncodeHeaders(hopt, b, &output); + g_compressor->EncodeHeaders(hopt, *b, &output); verify_frames(output, params.eof); merged = grpc_slice_merge(output.slices, output.count); grpc_slice_buffer_destroy_internal(&output); @@ -266,9 +257,7 @@ static void verify_continuation_headers(const char* key, const char* value, e[0].md = elem; e[0].prev = nullptr; e[0].next = nullptr; - b.list.head = &e[0]; - b.list.tail = &e[0]; - b.list.count = 1; + GPR_ASSERT(GRPC_ERROR_NONE == b->LinkTail(&e[0])); grpc_slice_buffer_init(&output); grpc_transport_one_way_stats stats; @@ -279,7 +268,7 @@ static void verify_continuation_headers(const char* key, const char* value, false, /* use_true_binary_metadata */ 150, /* max_frame_size */ &stats /* stats */}; - g_compressor->EncodeHeaders(hopt, b, &output); + g_compressor->EncodeHeaders(hopt, *b, &output); verify_frames(output, is_eof); grpc_slice_buffer_destroy_internal(&output); grpc_metadata_batch_destroy(&b); @@ -356,9 +345,7 @@ static void verify_table_size_change_match_elem_size(const char* key, e[0].md = elem; e[0].prev = nullptr; e[0].next = nullptr; - b.list.head = &e[0]; - b.list.tail = &e[0]; - b.list.count = 1; + GPR_ASSERT(GRPC_ERROR_NONE == b->LinkTail(&e[0])); grpc_slice_buffer_init(&output); grpc_transport_one_way_stats stats; @@ -369,7 +356,7 @@ static void verify_table_size_change_match_elem_size(const char* key, use_true_binary, /* use_true_binary_metadata */ 16384, /* max_frame_size */ &stats /* stats */}; - g_compressor->EncodeHeaders(hopt, b, &output); + g_compressor->EncodeHeaders(hopt, *b, &output); verify_frames(output, false); grpc_slice_buffer_destroy_internal(&output); grpc_metadata_batch_destroy(&b); diff --git a/test/cpp/microbenchmarks/bm_chttp2_hpack.cc b/test/cpp/microbenchmarks/bm_chttp2_hpack.cc index 1615aa575f4..b2ba9e3e4b0 100644 --- a/test/cpp/microbenchmarks/bm_chttp2_hpack.cc +++ b/test/cpp/microbenchmarks/bm_chttp2_hpack.cc @@ -71,7 +71,7 @@ static void BM_HpackEncoderEncodeDeadline(benchmark::State& state) { grpc_metadata_batch b; grpc_metadata_batch_init(&b); - b.deadline = saved_now + 30 * 1000; + b->SetDeadline(saved_now + 30 * 1000); grpc_core::HPackCompressor c; grpc_transport_one_way_stats stats; @@ -87,7 +87,7 @@ static void BM_HpackEncoderEncodeDeadline(benchmark::State& state) { static_cast(1024), &stats, }, - b, &outbuf); + *b, &outbuf); grpc_slice_buffer_reset_and_unref_internal(&outbuf); grpc_core::ExecCtx::Get()->Flush(); } @@ -136,7 +136,7 @@ static void BM_HpackEncoderEncodeHeader(benchmark::State& state) { static_cast(state.range(1) + kEnsureMaxFrameAtLeast), &stats, }, - b, &outbuf); + *b, &outbuf); if (!logged_representative_output && state.iterations() > 3) { logged_representative_output = true; for (size_t i = 0; i < outbuf.count; i++) { diff --git a/test/cpp/microbenchmarks/bm_chttp2_transport.cc b/test/cpp/microbenchmarks/bm_chttp2_transport.cc index 2b992c1561f..7b461a12e77 100644 --- a/test/cpp/microbenchmarks/bm_chttp2_transport.cc +++ b/test/cpp/microbenchmarks/bm_chttp2_transport.cc @@ -325,7 +325,7 @@ static void BM_StreamCreateSendInitialMetadataDestroy(benchmark::State& state) { grpc_metadata_batch b; grpc_metadata_batch_init(&b); - b.deadline = GRPC_MILLIS_INF_FUTURE; + b->ClearDeadline(); std::vector elems = Metadata::GetElems(); std::vector storage(elems.size()); for (size_t i = 0; i < elems.size(); i++) { @@ -429,7 +429,7 @@ static void BM_TransportStreamSend(benchmark::State& state) { grpc_core::ManualConstructor send_stream; grpc_metadata_batch b; grpc_metadata_batch_init(&b); - b.deadline = GRPC_MILLIS_INF_FUTURE; + b->ClearDeadline(); std::vector elems = RepresentativeClientInitialMetadata::GetElems(); std::vector storage(elems.size()); @@ -573,7 +573,7 @@ static void BM_TransportStreamRecv(benchmark::State& state) { grpc_metadata_batch_init(&b); grpc_metadata_batch b_recv; grpc_metadata_batch_init(&b_recv); - b.deadline = GRPC_MILLIS_INF_FUTURE; + b->ClearDeadline(); std::vector elems = RepresentativeClientInitialMetadata::GetElems(); std::vector storage(elems.size());