gnunet

Main GNUnet Logic
Log | Files | Refs | Submodules | README | LICENSE

testing_api_cmd_barrier_reached.c (4993B)


      1 /*
      2       This file is part of GNUnet
      3       Copyright (C) 2022 GNUnet e.V.
      4 
      5       GNUnet is free software: you can redistribute it and/or modify it
      6       under the terms of the GNU Affero General Public License as published
      7       by the Free Software Foundation, either version 3 of the License,
      8       or (at your option) any later version.
      9 
     10       GNUnet is distributed in the hope that it will be useful, but
     11       WITHOUT ANY WARRANTY; without even the implied warranty of
     12       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13       Affero General Public License for more details.
     14 
     15       You should have received a copy of the GNU Affero General Public License
     16       along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18      SPDX-License-Identifier: AGPL3.0-or-later
     19  */
     20 
     21 /**
     22  * @file testing/testing_api_cmd_barrier_reached.c
     23  * @brief Command to signal barrier was reached.
     24  * @author t3sserakt
     25  */
     26 #include "platform.h"
     27 #include "gnunet_testing_lib.h"
     28 #include "testing_api_loop.h"
     29 #include "testing_cmds.h"
     30 
     31 /**
     32  * Generic logging shortcut
     33  */
     34 #define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
     35 
     36 /**
     37  * Struct with information for callbacks.
     38  *
     39  */
     40 struct BarrierReachedState
     41 {
     42   /**
     43    * Context for our asynchronous completion.
     44    */
     45   struct GNUNET_TESTING_AsyncContext ac;
     46 
     47   /**
     48    * The label of this command.
     49    */
     50   const char *label;
     51 
     52   /**
     53    * The name of the barrier this commands wait (if finishing asynchronous) for or/and reaches.
     54    */
     55   const char *barrier_name;
     56 
     57 };
     58 
     59 
     60 /**
     61  * Run the command.
     62  *
     63  * @param cls closure.
     64  * @param is the interpreter state.
     65  */
     66 static void
     67 barrier_reached_run (void *cls,
     68                      struct GNUNET_TESTING_Interpreter *is)
     69 {
     70   struct BarrierReachedState *brs = cls;
     71   struct GNUNET_TESTING_Barrier *barrier;
     72 
     73   barrier = GNUNET_TESTING_get_barrier_ (is,
     74                                          brs->barrier_name);
     75   if (NULL == barrier)
     76   {
     77     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     78                 "No barrier `%s'\n",
     79                 brs->barrier_name);
     80     GNUNET_TESTING_async_fail (&brs->ac);
     81     return;
     82   }
     83   if (barrier->satisfied)
     84   {
     85     GNUNET_TESTING_async_finish (&brs->ac);
     86     return;
     87   }
     88   GNUNET_array_append (barrier->waiting,
     89                        barrier->cnt_waiting,
     90                        &brs->ac);
     91   if (barrier->inherited)
     92   {
     93     struct GNUNET_TESTING_CommandBarrierReached cbr = {
     94       .header.size = htons (sizeof (cbr)),
     95       .header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_BARRIER_REACHED)
     96     };
     97 
     98     GNUNET_TESTING_barrier_name_hash_ (brs->barrier_name,
     99                                        &cbr.barrier_key);
    100     GNUNET_TESTING_loop_notify_parent_ (is,
    101                                         &cbr.header);
    102     return;
    103   }
    104   barrier->reached++;
    105   if (barrier->reached == barrier->expected_reaches)
    106   {
    107     struct GNUNET_TESTING_CommandBarrierSatisfied cbs = {
    108       .header.size = htons (sizeof (cbs)),
    109       .header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_BARRIER_CROSSABLE)
    110     };
    111 
    112     GNUNET_TESTING_barrier_name_hash_ (brs->barrier_name,
    113                                        &cbs.barrier_key);
    114     barrier->satisfied = true;
    115     GNUNET_TESTING_loop_notify_children_ (is,
    116                                           &cbs.header);
    117   }
    118   if (barrier->satisfied)
    119   {
    120     GNUNET_TESTING_async_finish (&brs->ac);
    121     for (unsigned int i = 0; i<barrier->cnt_waiting; i++)
    122       GNUNET_TESTING_async_finish (barrier->waiting[i]);
    123     GNUNET_array_grow (barrier->waiting,
    124                        barrier->cnt_waiting,
    125                        0);
    126     return;
    127   }
    128 }
    129 
    130 
    131 /**
    132  * Cleanup the state from a "barrier reached" CMD, and possibly
    133  * cancel a pending operation thereof.
    134  *
    135  * @param cls closure.
    136  */
    137 static void
    138 barrier_reached_cleanup (void *cls)
    139 {
    140   struct BarrierReachedState *brs = cls;
    141 
    142   GNUNET_free (brs);
    143 }
    144 
    145 
    146 /**
    147  * Offer internal data from a "batch" CMD, to other commands.
    148  *
    149  * @param cls closure.
    150  * @param[out] ret result.
    151  * @param trait name of the trait.
    152  * @param index index number of the object to offer.
    153  * @return #GNUNET_OK on success.
    154  */
    155 static enum GNUNET_GenericReturnValue
    156 barrier_reached_traits (void *cls,
    157                         const void **ret,
    158                         const char *trait,
    159                         unsigned int index)
    160 {
    161   struct GNUNET_TESTING_Trait traits[] = {
    162     GNUNET_TESTING_trait_end ()
    163   };
    164 
    165   return GNUNET_TESTING_get_trait (traits,
    166                                    ret,
    167                                    trait,
    168                                    index);
    169 }
    170 
    171 
    172 struct GNUNET_TESTING_Command
    173 GNUNET_TESTING_cmd_barrier_reached (
    174   const char *label,
    175   const char *barrier_label)
    176 {
    177   struct BarrierReachedState *brs;
    178 
    179   brs = GNUNET_new (struct BarrierReachedState);
    180   brs->label = label;
    181   brs->barrier_name = barrier_label;
    182   return GNUNET_TESTING_command_new_ac (
    183     brs,
    184     label,
    185     &barrier_reached_run,
    186     &barrier_reached_cleanup,
    187     &barrier_reached_traits,
    188     &brs->ac);
    189 }