LCOV - code coverage report
Current view: top level - src/core/transport - stream_op.c (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 179 190 94.2 %
Date: 2015-10-10 Functions: 25 26 96.2 %

          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 : }

Generated by: LCOV version 1.10