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 }