Line data Source code
1 : /*
2 : *
3 : * Copyright 2015, Google Inc.
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions are
8 : * met:
9 : *
10 : * * Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * * Redistributions in binary form must reproduce the above
13 : * copyright notice, this list of conditions and the following disclaimer
14 : * in the documentation and/or other materials provided with the
15 : * distribution.
16 : * * Neither the name of Google Inc. nor the names of its
17 : * contributors may be used to endorse or promote products derived from
18 : * this software without specific prior written permission.
19 : *
20 : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 : * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 : * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 : * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 : * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 : *
32 : */
33 :
34 : #include "src/core/transport/stream_op.h"
35 :
36 : #include <string.h>
37 :
38 : #include <grpc/support/alloc.h>
39 : #include <grpc/support/log.h>
40 :
41 : /* Exponential growth function: Given x, return a larger x.
42 : Currently we grow by 1.5 times upon reallocation. */
43 : #define GROW(x) (3 * (x) / 2)
44 :
45 13511939 : void grpc_sopb_init(grpc_stream_op_buffer *sopb) {
46 13511939 : sopb->ops = sopb->inlined_ops;
47 13511939 : sopb->nops = 0;
48 13511939 : sopb->capacity = GRPC_SOPB_INLINE_ELEMENTS;
49 13511939 : }
50 :
51 13490580 : void grpc_sopb_destroy(grpc_stream_op_buffer *sopb) {
52 13490580 : grpc_stream_ops_unref_owned_objects(sopb->ops, sopb->nops);
53 13499846 : if (sopb->ops != sopb->inlined_ops) gpr_free(sopb->ops);
54 13499846 : }
55 :
56 100 : void grpc_sopb_reset(grpc_stream_op_buffer *sopb) {
57 100 : grpc_stream_ops_unref_owned_objects(sopb->ops, sopb->nops);
58 100 : sopb->nops = 0;
59 100 : }
60 :
61 9374418 : void grpc_sopb_swap(grpc_stream_op_buffer *a, grpc_stream_op_buffer *b) {
62 9374418 : GPR_SWAP(size_t, a->nops, b->nops);
63 9374418 : GPR_SWAP(size_t, a->capacity, b->capacity);
64 :
65 9374418 : if (a->ops == a->inlined_ops) {
66 8273923 : if (b->ops == b->inlined_ops) {
67 : /* swap contents of inlined buffer */
68 : grpc_stream_op temp[GRPC_SOPB_INLINE_ELEMENTS];
69 7598152 : memcpy(temp, a->ops, b->nops * sizeof(grpc_stream_op));
70 7598152 : memcpy(a->ops, b->ops, a->nops * sizeof(grpc_stream_op));
71 7598152 : memcpy(b->ops, temp, b->nops * sizeof(grpc_stream_op));
72 : } else {
73 : /* a is inlined, b is not - copy a inlined into b, fix pointers */
74 675771 : a->ops = b->ops;
75 675771 : b->ops = b->inlined_ops;
76 675771 : memcpy(b->ops, a->inlined_ops, b->nops * sizeof(grpc_stream_op));
77 : }
78 1100495 : } else if (b->ops == b->inlined_ops) {
79 : /* b is inlined, a is not - copy b inlined int a, fix pointers */
80 670352 : b->ops = a->ops;
81 670352 : a->ops = a->inlined_ops;
82 670352 : memcpy(a->ops, b->inlined_ops, a->nops * sizeof(grpc_stream_op));
83 : } else {
84 : /* no inlining: easy swap */
85 430143 : GPR_SWAP(grpc_stream_op *, a->ops, b->ops);
86 : }
87 9374418 : }
88 :
89 13498297 : void grpc_stream_ops_unref_owned_objects(grpc_stream_op *ops, size_t nops) {
90 : size_t i;
91 13768466 : for (i = 0; i < nops; i++) {
92 270171 : switch (ops[i].type) {
93 : case GRPC_OP_SLICE:
94 284 : gpr_slice_unref(ops[i].data.slice);
95 284 : break;
96 : case GRPC_OP_METADATA:
97 269647 : grpc_metadata_batch_destroy(&ops[i].data.metadata);
98 269645 : break;
99 : case GRPC_NO_OP:
100 : case GRPC_OP_BEGIN_MESSAGE:
101 240 : break;
102 : }
103 : }
104 13498295 : }
105 :
106 6180 : static void expandto(grpc_stream_op_buffer *sopb, size_t new_capacity) {
107 6180 : sopb->capacity = new_capacity;
108 6180 : if (sopb->ops == sopb->inlined_ops) {
109 5802 : sopb->ops = gpr_malloc(sizeof(grpc_stream_op) * new_capacity);
110 5802 : memcpy(sopb->ops, sopb->inlined_ops, sopb->nops * sizeof(grpc_stream_op));
111 : } else {
112 378 : sopb->ops = gpr_realloc(sopb->ops, sizeof(grpc_stream_op) * new_capacity);
113 : }
114 6180 : }
115 :
116 24452934 : static grpc_stream_op *add(grpc_stream_op_buffer *sopb) {
117 : grpc_stream_op *out;
118 :
119 24452934 : GPR_ASSERT(sopb->nops <= sopb->capacity);
120 24452934 : if (sopb->nops == sopb->capacity) {
121 5805 : expandto(sopb, GROW(sopb->capacity));
122 : }
123 24462427 : out = sopb->ops + sopb->nops;
124 24462427 : sopb->nops++;
125 24462427 : return out;
126 : }
127 :
128 3 : void grpc_sopb_add_no_op(grpc_stream_op_buffer *sopb) {
129 3 : add(sopb)->type = GRPC_NO_OP;
130 3 : }
131 :
132 5992435 : void grpc_sopb_add_begin_message(grpc_stream_op_buffer *sopb, gpr_uint32 length,
133 : gpr_uint32 flags) {
134 5992435 : grpc_stream_op *op = add(sopb);
135 5995043 : op->type = GRPC_OP_BEGIN_MESSAGE;
136 5995043 : op->data.begin_message.length = length;
137 5995043 : op->data.begin_message.flags = flags;
138 5995043 : }
139 :
140 8487783 : void grpc_sopb_add_metadata(grpc_stream_op_buffer *sopb,
141 : grpc_metadata_batch b) {
142 8487783 : grpc_stream_op *op = add(sopb);
143 8493359 : op->type = GRPC_OP_METADATA;
144 8493359 : op->data.metadata = b;
145 8493359 : }
146 :
147 10051125 : void grpc_sopb_add_slice(grpc_stream_op_buffer *sopb, gpr_slice slice) {
148 10051125 : grpc_stream_op *op = add(sopb);
149 10052982 : op->type = GRPC_OP_SLICE;
150 10052982 : op->data.slice = slice;
151 10052982 : }
152 :
153 10109184 : void grpc_sopb_append(grpc_stream_op_buffer *sopb, grpc_stream_op *ops,
154 : size_t nops) {
155 10109184 : size_t orig_nops = sopb->nops;
156 10109184 : size_t new_nops = orig_nops + nops;
157 :
158 10109184 : if (new_nops > sopb->capacity) {
159 375 : expandto(sopb, GPR_MAX(GROW(sopb->capacity), new_nops));
160 : }
161 :
162 10109184 : memcpy(sopb->ops + orig_nops, ops, sizeof(grpc_stream_op) * nops);
163 10109184 : sopb->nops = new_nops;
164 10109184 : }
165 :
166 4042139 : void grpc_sopb_move_to(grpc_stream_op_buffer *src, grpc_stream_op_buffer *dst) {
167 4042139 : if (src->nops == 0) {
168 0 : return;
169 : }
170 4042139 : if (dst->nops == 0) {
171 4036259 : grpc_sopb_swap(src, dst);
172 4036559 : return;
173 : }
174 5880 : grpc_sopb_append(dst, src->ops, src->nops);
175 5880 : src->nops = 0;
176 : }
177 :
178 122128382 : static void assert_valid_list(grpc_mdelem_list *list) {
179 : #ifndef NDEBUG
180 : grpc_linked_mdelem *l;
181 :
182 122128382 : GPR_ASSERT((list->head == NULL) == (list->tail == NULL));
183 244749899 : if (!list->head) return;
184 91154301 : GPR_ASSERT(list->head->prev == NULL);
185 91154301 : GPR_ASSERT(list->tail->next == NULL);
186 91154301 : GPR_ASSERT((list->head == list->tail) == (list->head->next == NULL));
187 :
188 435855517 : for (l = list->head; l; l = l->next) {
189 344208081 : GPR_ASSERT(l->md);
190 344701216 : GPR_ASSERT((l->prev == NULL) == (l == list->head));
191 344701216 : GPR_ASSERT((l->next == NULL) == (l == list->tail));
192 344701216 : if (l->next) GPR_ASSERT(l->next->prev == l);
193 344701216 : if (l->prev) GPR_ASSERT(l->prev->next == l);
194 : }
195 : #endif /* NDEBUG */
196 : }
197 :
198 : #ifndef NDEBUG
199 8223126 : void grpc_metadata_batch_assert_ok(grpc_metadata_batch *batch) {
200 8223126 : assert_valid_list(&batch->list);
201 8221997 : assert_valid_list(&batch->garbage);
202 8222317 : }
203 : #endif /* NDEBUG */
204 :
205 110586 : void grpc_metadata_batch_init(grpc_metadata_batch *batch) {
206 110586 : batch->list.head = batch->list.tail = batch->garbage.head =
207 110586 : batch->garbage.tail = NULL;
208 110586 : batch->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
209 110586 : }
210 :
211 269633 : void grpc_metadata_batch_destroy(grpc_metadata_batch *batch) {
212 : grpc_linked_mdelem *l;
213 270869 : for (l = batch->list.head; l; l = l->next) {
214 1236 : GRPC_MDELEM_UNREF(l->md);
215 : }
216 269661 : for (l = batch->garbage.head; l; l = l->next) {
217 28 : GRPC_MDELEM_UNREF(l->md);
218 : }
219 269633 : }
220 :
221 4105290 : void grpc_metadata_batch_add_head(grpc_metadata_batch *batch,
222 : grpc_linked_mdelem *storage,
223 : grpc_mdelem *elem_to_add) {
224 4105290 : GPR_ASSERT(elem_to_add);
225 4105290 : storage->md = elem_to_add;
226 4105290 : grpc_metadata_batch_link_head(batch, storage);
227 4103122 : }
228 :
229 17416249 : static void link_head(grpc_mdelem_list *list, grpc_linked_mdelem *storage) {
230 17416249 : assert_valid_list(list);
231 17459176 : GPR_ASSERT(storage->md);
232 17459176 : storage->prev = NULL;
233 17459176 : storage->next = list->head;
234 17459176 : if (list->head != NULL) {
235 13356651 : list->head->prev = storage;
236 : } else {
237 4102525 : list->tail = storage;
238 : }
239 17459176 : list->head = storage;
240 17459176 : assert_valid_list(list);
241 17404283 : }
242 :
243 6906239 : void grpc_metadata_batch_link_head(grpc_metadata_batch *batch,
244 : grpc_linked_mdelem *storage) {
245 6906239 : link_head(&batch->list, storage);
246 6902536 : }
247 :
248 12210116 : void grpc_metadata_batch_add_tail(grpc_metadata_batch *batch,
249 : grpc_linked_mdelem *storage,
250 : grpc_mdelem *elem_to_add) {
251 12210116 : GPR_ASSERT(elem_to_add);
252 12210116 : storage->md = elem_to_add;
253 12210116 : grpc_metadata_batch_link_tail(batch, storage);
254 12182008 : }
255 :
256 12210120 : static void link_tail(grpc_mdelem_list *list, grpc_linked_mdelem *storage) {
257 12210120 : assert_valid_list(list);
258 12208016 : GPR_ASSERT(storage->md);
259 12208016 : storage->prev = list->tail;
260 12208016 : storage->next = NULL;
261 12208016 : storage->reserved = NULL;
262 12208016 : if (list->tail != NULL) {
263 9606398 : list->tail->next = storage;
264 : } else {
265 2601618 : list->head = storage;
266 : }
267 12208016 : list->tail = storage;
268 12208016 : assert_valid_list(list);
269 12173999 : }
270 :
271 12209321 : void grpc_metadata_batch_link_tail(grpc_metadata_batch *batch,
272 : grpc_linked_mdelem *storage) {
273 12209321 : link_tail(&batch->list, storage);
274 12181619 : }
275 :
276 0 : void grpc_metadata_batch_merge(grpc_metadata_batch *target,
277 : grpc_metadata_batch *to_add) {
278 : grpc_linked_mdelem *l;
279 : grpc_linked_mdelem *next;
280 0 : for (l = to_add->list.head; l; l = next) {
281 0 : next = l->next;
282 0 : link_tail(&target->list, l);
283 : }
284 0 : for (l = to_add->garbage.head; l; l = next) {
285 0 : next = l->next;
286 0 : link_tail(&target->garbage, l);
287 : }
288 0 : }
289 :
290 64 : void grpc_metadata_batch_move(grpc_metadata_batch *dst,
291 : grpc_metadata_batch *src) {
292 64 : *dst = *src;
293 64 : memset(src, 0, sizeof(grpc_metadata_batch));
294 64 : }
295 :
296 9482567 : void grpc_metadata_batch_filter(grpc_metadata_batch *batch,
297 : grpc_mdelem *(*filter)(void *user_data,
298 : grpc_mdelem *elem),
299 : void *user_data) {
300 : grpc_linked_mdelem *l;
301 : grpc_linked_mdelem *next;
302 :
303 9482567 : assert_valid_list(&batch->list);
304 9483085 : assert_valid_list(&batch->garbage);
305 42967955 : for (l = batch->list.head; l; l = next) {
306 33496626 : grpc_mdelem *orig = l->md;
307 33496626 : grpc_mdelem *filt = filter(user_data, orig);
308 33633394 : next = l->next;
309 33633394 : if (filt == NULL) {
310 10588262 : if (l->prev) {
311 4001457 : l->prev->next = l->next;
312 : }
313 10588262 : if (l->next) {
314 9196508 : l->next->prev = l->prev;
315 : }
316 10588262 : if (batch->list.head == l) {
317 6600054 : batch->list.head = l->next;
318 : }
319 10588262 : if (batch->list.tail == l) {
320 1402722 : batch->list.tail = l->prev;
321 : }
322 10588262 : assert_valid_list(&batch->list);
323 10586215 : link_head(&batch->garbage, l);
324 23045132 : } else if (filt != orig) {
325 0 : GRPC_MDELEM_UNREF(orig);
326 0 : l->md = filt;
327 : }
328 : }
329 9471329 : assert_valid_list(&batch->list);
330 9474047 : assert_valid_list(&batch->garbage);
331 9473126 : }
|