aboutsummaryrefslogtreecommitdiff
path: root/src/testbed/testbed_api_barriers.c
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2013-08-30 14:55:13 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2013-08-30 14:55:13 +0000
commit5e1efe185cf484018f53dd33d64e546ac042fdee (patch)
treee1369e8e1a239426d4ba2d81bb31571bbd4f82eb /src/testbed/testbed_api_barriers.c
parent7d8d536bbaa0f72587552af517f643e3c05e7a6f (diff)
downloadgnunet-5e1efe185cf484018f53dd33d64e546ac042fdee.tar.gz
gnunet-5e1efe185cf484018f53dd33d64e546ac042fdee.zip
- towards testbed barriers
Diffstat (limited to 'src/testbed/testbed_api_barriers.c')
-rw-r--r--src/testbed/testbed_api_barriers.c221
1 files changed, 221 insertions, 0 deletions
diff --git a/src/testbed/testbed_api_barriers.c b/src/testbed/testbed_api_barriers.c
new file mode 100644
index 000000000..231e00600
--- /dev/null
+++ b/src/testbed/testbed_api_barriers.c
@@ -0,0 +1,221 @@
1/*
2 This file is part of GNUnet.
3 (C) 2008--2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file testbed/testbed_api_barriers.c
23 * @brief API implementation for testbed barriers
24 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
25 */
26
27#include "platform.h"
28#include "gnunet_testbed_service.h"
29#include "testbed_api.h"
30
31/**
32 * Handle for barrier
33 */
34struct GNUNET_TESTBED_Barrier
35{
36 /**
37 * hashcode identifying this barrier in the hashmap
38 */
39 struct GNUNET_HashCode key;
40
41 /**
42 * The controller handle given while initiliasing this barrier
43 */
44 struct GNUNET_TESTBED_Controller *c;
45
46 /**
47 * The name of the barrier
48 */
49 char *name;
50
51 /**
52 * The continuation callback to call when we have a status update on this
53 */
54 GNUNET_TESTBED_barrier_status_cb cb;
55
56 /**
57 * the closure for the above callback
58 */
59 void *cls;
60
61};
62
63
64/**
65 * handle for hashtable of barrier handles
66 */
67static struct GNUNET_CONTAINER_MultiHashMap *barrier_map;
68
69
70/**
71 * Remove a barrier and it was the last one in the barrier hash map, destroy the
72 * hash map
73 *
74 * @param barrier the barrier to remove
75 */
76static void
77barrier_remove (struct GNUNET_TESTBED_Barrier *barrier)
78{
79 GNUNET_assert (NULL != barrier_map); /* No barriers present */
80 GNUNET_assert (GNUNET_OK ==
81 GNUNET_CONTAINER_multihashmap_remove (barrier_map,
82 &barrier->key,
83 barrier));
84 GNUNET_free (barrier->name);
85 GNUNET_free (barrier);
86 if (0 == GNUNET_CONTAINER_multihashmap_size (barrier_map))
87 {
88 GNUNET_CONTAINER_multihashmap_destroy (barrier_map);
89 barrier_map = NULL;
90 }
91}
92
93
94/**
95 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages
96 *
97 * @param c the controller handle to determine the connection this message
98 * belongs to
99 * @param msg the barrier status message
100 * @return GNUNET_OK to keep the connection active; GNUNET_SYSERR to tear it
101 * down signalling an error
102 */
103int
104GNUNET_TESTBED_handle_barrier_status_ (struct GNUNET_TESTBED_Controller *c,
105 const struct GNUNET_TESTBED_BarrierStatus
106 *msg)
107{
108 struct GNUNET_TESTBED_Barrier *barrier;
109 char *emsg;
110 const char *name;
111 struct GNUNET_HashCode key;
112 size_t emsg_len;
113 int status;
114 uint16_t msize;
115 uint16_t name_len;
116
117 emsg = NULL;
118 barrier = NULL;
119 msize = ntohs (msg->header.size);
120 name = msg->data;
121 name_len = ntohs (msg->name_len);
122 if ( (sizeof (struct GNUNET_TESTBED_BarrierStatus) + name_len + 1 > msize)
123 || ('\0' != name[name_len]) )
124 {
125 GNUNET_break_op (0);
126 return GNUNET_SYSERR;
127 }
128 status = ntohs (msg->status);
129 if (0 != status)
130 {
131 status = -1;
132 emsg_len = msize - (sizeof (struct GNUNET_TESTBED_BarrierStatus) + name_len
133 + 1);
134 if (0 == emsg_len)
135 {
136 GNUNET_break_op (0);
137 return GNUNET_SYSERR;
138 }
139 emsg_len++;
140 emsg = GNUNET_malloc (emsg_len);
141 emsg_len--;
142 emsg[emsg_len] = '\0';
143 (void) memcpy (emsg, msg->data + name_len + 1, emsg_len);
144 }
145 if (NULL == barrier_map)
146 goto cleanup;
147 GNUNET_CRYPTO_hash (name, name_len, &key);
148 barrier = GNUNET_CONTAINER_multihashmap_get (barrier_map, &key);
149 if (NULL == barrier)
150 goto cleanup;
151 GNUNET_assert (NULL != barrier->cb);
152 barrier->cb (barrier->cls, name, barrier, status, emsg);
153
154 cleanup:
155 GNUNET_free_non_null (emsg);
156 if (NULL != barrier)
157 barrier_remove (barrier);
158 return GNUNET_OK;
159}
160
161
162/**
163 * Initialise a barrier and call the given callback when the required percentage
164 * of peers (quorum) reach the barrier OR upon error.
165 *
166 * @param controller the handle to the controller
167 * @param name identification name of the barrier
168 * @param quorum the percentage of peers that is required to reach the barrier.
169 * Peers signal reaching a barrier by calling
170 * GNUNET_TESTBED_barrier_reached().
171 * @param cb the callback to call when the barrier is reached or upon error.
172 * Cannot be NULL.
173 * @param cls closure for the above callback
174 * @return barrier handle; NULL upon error
175 */
176struct GNUNET_TESTBED_Barrier *
177GNUNET_TESTBED_barrier_init (struct GNUNET_TESTBED_Controller *controller,
178 const char *name,
179 unsigned int quorum,
180 GNUNET_TESTBED_barrier_status_cb cb, void *cls)
181{
182 struct GNUNET_TESTBED_Barrier *barrier;
183 struct GNUNET_HashCode key;
184 size_t name_len;
185
186 GNUNET_assert (quorum <= 100);
187 GNUNET_assert (NULL != cb);
188 name_len = strlen (name);
189 GNUNET_assert (0 < name_len);
190 GNUNET_CRYPTO_hash (name, name_len, &key);
191 if (NULL == barrier_map)
192 barrier_map = GNUNET_CONTAINER_multihashmap_create (3, GNUNET_YES);
193 if (GNUNET_YES ==
194 GNUNET_CONTAINER_multihashmap_contains (barrier_map, &key))
195 {
196 GNUNET_break (0);
197 return NULL;
198 }
199 barrier = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Barrier));
200 barrier->name = GNUNET_strdup (name);
201 barrier->cb = cb;
202 barrier->cls = cls;
203 (void) memcpy (&barrier->key, &key, sizeof (struct GNUNET_HashCode));
204 GNUNET_assert (GNUNET_OK ==
205 GNUNET_CONTAINER_multihashmap_put (barrier_map, &barrier->key,
206 barrier,
207 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
208 return barrier;
209}
210
211
212/**
213 * Cancel a barrier.
214 *
215 * @param barrier the barrier handle
216 */
217void
218GNUNET_TESTBED_barrier_cancel (struct GNUNET_TESTBED_Barrier *barrier)
219{
220 barrier_remove (barrier);
221}