diff options
author | Sree Harsha Totakura <totakura@in.tum.de> | 2013-08-30 14:55:13 +0000 |
---|---|---|
committer | Sree Harsha Totakura <totakura@in.tum.de> | 2013-08-30 14:55:13 +0000 |
commit | 5e1efe185cf484018f53dd33d64e546ac042fdee (patch) | |
tree | e1369e8e1a239426d4ba2d81bb31571bbd4f82eb /src/testbed/testbed_api_barriers.c | |
parent | 7d8d536bbaa0f72587552af517f643e3c05e7a6f (diff) | |
download | gnunet-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.c | 221 |
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 | */ | ||
34 | struct 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 | */ | ||
67 | static 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 | */ | ||
76 | static void | ||
77 | barrier_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 | */ | ||
103 | int | ||
104 | GNUNET_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 | */ | ||
176 | struct GNUNET_TESTBED_Barrier * | ||
177 | GNUNET_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 | */ | ||
217 | void | ||
218 | GNUNET_TESTBED_barrier_cancel (struct GNUNET_TESTBED_Barrier *barrier) | ||
219 | { | ||
220 | barrier_remove (barrier); | ||
221 | } | ||