3 * Copyright 2015 gRPC authors.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 #ifndef GRPC_CORE_LIB_TRANSPORT_METADATA_BATCH_H
20 #define GRPC_CORE_LIB_TRANSPORT_METADATA_BATCH_H
22 #include <grpc/support/port_platform.h>
26 #include "absl/types/optional.h"
28 #include <grpc/grpc.h>
29 #include <grpc/slice.h>
30 #include <grpc/support/time.h>
32 #include "src/core/lib/iomgr/exec_ctx.h"
33 #include "src/core/lib/transport/metadata.h"
34 #include "src/core/lib/transport/static_metadata.h"
36 typedef struct grpc_linked_mdelem {
37 grpc_linked_mdelem() {}
40 struct grpc_linked_mdelem* next = nullptr;
41 struct grpc_linked_mdelem* prev = nullptr;
45 typedef struct grpc_mdelem_list {
47 size_t default_count; // Number of default keys.
48 grpc_linked_mdelem* head;
49 grpc_linked_mdelem* tail;
52 typedef struct grpc_metadata_batch {
53 /** Metadata elements in this batch */
54 grpc_mdelem_list list;
55 grpc_metadata_batch_callouts idx;
56 /** Used to calculate grpc-timeout at the point of sending,
57 or GRPC_MILLIS_INF_FUTURE if this batch does not need to send a
61 template <typename Encoder>
62 void Encode(Encoder* encoder) const {
63 for (auto* l = list.head; l; l = l->next) {
64 encoder->Encode(l->md);
66 if (deadline != GRPC_MILLIS_INF_FUTURE) encoder->EncodeDeadline(deadline);
68 } grpc_metadata_batch;
70 void grpc_metadata_batch_init(grpc_metadata_batch* batch);
71 void grpc_metadata_batch_destroy(grpc_metadata_batch* batch);
72 void grpc_metadata_batch_clear(grpc_metadata_batch* batch);
73 bool grpc_metadata_batch_is_empty(grpc_metadata_batch* batch);
75 /* Returns the transport size of the batch. */
76 size_t grpc_metadata_batch_size(grpc_metadata_batch* batch);
78 /** Remove \a storage from the batch, unreffing the mdelem contained */
79 void grpc_metadata_batch_remove(grpc_metadata_batch* batch,
80 grpc_linked_mdelem* storage);
81 void grpc_metadata_batch_remove(grpc_metadata_batch* batch,
82 grpc_metadata_batch_callouts_index idx);
84 /** Substitute a new mdelem for an old value */
85 grpc_error_handle grpc_metadata_batch_substitute(grpc_metadata_batch* batch,
86 grpc_linked_mdelem* storage,
87 grpc_mdelem new_mdelem);
89 void grpc_metadata_batch_set_value(grpc_linked_mdelem* storage,
90 const grpc_slice& value);
92 /** Returns metadata value(s) for the specified key.
93 If the key is not present in the batch, returns absl::nullopt.
94 If the key is present exactly once in the batch, returns a string_view of
96 If the key is present more than once in the batch, constructs a
97 comma-concatenated string of all values in concatenated_value and returns a
98 string_view of that string. */
99 absl::optional<absl::string_view> grpc_metadata_batch_get_value(
100 grpc_metadata_batch* batch, absl::string_view target_key,
101 std::string* concatenated_value);
103 /** Add \a storage to the beginning of \a batch. storage->md is
105 \a storage is owned by the caller and must survive for the
106 lifetime of batch. This usually means it should be around
107 for the lifetime of the call. */
108 grpc_error_handle grpc_metadata_batch_link_head(grpc_metadata_batch* batch,
109 grpc_linked_mdelem* storage)
110 GRPC_MUST_USE_RESULT;
111 grpc_error_handle grpc_metadata_batch_link_head(
112 grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
113 grpc_metadata_batch_callouts_index idx) GRPC_MUST_USE_RESULT;
115 /** Add \a storage to the end of \a batch. storage->md is
117 \a storage is owned by the caller and must survive for the
118 lifetime of batch. This usually means it should be around
119 for the lifetime of the call. */
120 grpc_error_handle grpc_metadata_batch_link_tail(grpc_metadata_batch* batch,
121 grpc_linked_mdelem* storage)
122 GRPC_MUST_USE_RESULT;
123 grpc_error_handle grpc_metadata_batch_link_tail(
124 grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
125 grpc_metadata_batch_callouts_index idx) GRPC_MUST_USE_RESULT;
127 /** Add \a elem_to_add as the first element in \a batch, using
128 \a storage as backing storage for the linked list element.
129 \a storage is owned by the caller and must survive for the
130 lifetime of batch. This usually means it should be around
131 for the lifetime of the call.
132 Takes ownership of \a elem_to_add */
133 grpc_error_handle grpc_metadata_batch_add_head(
134 grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
135 grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT;
137 // TODO(arjunroy, roth): Remove redundant methods.
138 // add/link_head/tail are almost identical.
139 inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_head(
140 grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
141 grpc_metadata_batch_callouts_index idx) {
142 return grpc_metadata_batch_link_head(batch, storage, idx);
145 inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_head(
146 grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
147 grpc_mdelem elem_to_add, grpc_metadata_batch_callouts_index idx) {
148 GPR_DEBUG_ASSERT(!GRPC_MDISNULL(elem_to_add));
149 storage->md = elem_to_add;
150 return grpc_metadata_batch_add_head(batch, storage, idx);
153 /** Add \a elem_to_add as the last element in \a batch, using
154 \a storage as backing storage for the linked list element.
155 \a storage is owned by the caller and must survive for the
156 lifetime of batch. This usually means it should be around
157 for the lifetime of the call.
158 Takes ownership of \a elem_to_add */
159 grpc_error_handle grpc_metadata_batch_add_tail(
160 grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
161 grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT;
163 inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_tail(
164 grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
165 grpc_metadata_batch_callouts_index idx) {
166 return grpc_metadata_batch_link_tail(batch, storage, idx);
169 inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_tail(
170 grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
171 grpc_mdelem elem_to_add, grpc_metadata_batch_callouts_index idx) {
172 GPR_DEBUG_ASSERT(!GRPC_MDISNULL(elem_to_add));
173 storage->md = elem_to_add;
174 return grpc_metadata_batch_add_tail(batch, storage, idx);
177 grpc_error_handle grpc_attach_md_to_error(grpc_error_handle src,
180 struct grpc_filtered_mdelem {
181 grpc_error_handle error;
184 #define GRPC_FILTERED_ERROR(error) \
185 { (error), GRPC_MDNULL }
186 #define GRPC_FILTERED_MDELEM(md) \
187 { GRPC_ERROR_NONE, (md) }
188 #define GRPC_FILTERED_REMOVE() \
189 { GRPC_ERROR_NONE, GRPC_MDNULL }
191 typedef grpc_filtered_mdelem (*grpc_metadata_batch_filter_func)(
192 void* user_data, grpc_mdelem elem);
193 grpc_error_handle grpc_metadata_batch_filter(
194 grpc_metadata_batch* batch, grpc_metadata_batch_filter_func func,
195 void* user_data, const char* composite_error_string) GRPC_MUST_USE_RESULT;
198 void grpc_metadata_batch_assert_ok(grpc_metadata_batch* batch);
200 #define grpc_metadata_batch_assert_ok(batch) \
205 /// Copies \a src to \a dst. \a storage must point to an array of
206 /// \a grpc_linked_mdelem structs of at least the same size as \a src.
208 /// For each mdelem in \a src, if the mdelem is of storage types
209 /// GRPC_MDELEM_STORAGE_INTERNED or GRPC_MDELEM_STORAGE_ALLOCATED,
210 /// refs the original mdelem for the copy. Otherwise, makes a new
211 /// mdelem that will hold its own refs to the key and value slices.
213 /// Currently used only in the retry code.
214 void grpc_metadata_batch_copy(grpc_metadata_batch* src,
215 grpc_metadata_batch* dst,
216 grpc_linked_mdelem* storage);
218 void grpc_metadata_batch_move(grpc_metadata_batch* src,
219 grpc_metadata_batch* dst);
221 #endif /* GRPC_CORE_LIB_TRANSPORT_METADATA_BATCH_H */