aboutsummaryrefslogtreecommitdiff
path: root/src/consensus/gnunet-consensus.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/consensus/gnunet-consensus.c')
-rw-r--r--src/consensus/gnunet-consensus.c360
1 files changed, 222 insertions, 138 deletions
diff --git a/src/consensus/gnunet-consensus.c b/src/consensus/gnunet-consensus.c
index cd267f5ec..c8a5593f1 100644
--- a/src/consensus/gnunet-consensus.c
+++ b/src/consensus/gnunet-consensus.c
@@ -20,210 +20,283 @@
20 20
21/** 21/**
22 * @file consensus/gnunet-consensus.c 22 * @file consensus/gnunet-consensus.c
23 * @brief 23 * @brief profiling tool for gnunet-consensus
24 * @author Florian Dold 24 * @author Florian Dold
25 */ 25 */
26#include "platform.h" 26#include "platform.h"
27#include "gnunet_common.h"
27#include "gnunet_util_lib.h" 28#include "gnunet_util_lib.h"
28#include "gnunet_consensus_service.h" 29#include "gnunet_consensus_service.h"
30#include "gnunet_testbed_service.h"
29 31
32static unsigned int num_peers = 2;
30 33
34static unsigned int replication = 1;
31 35
32/** 36static unsigned int num_values = 5;
33 * Handle to the consensus service
34 */
35static struct GNUNET_CONSENSUS_Handle *consensus;
36/**
37 * Session id
38 */
39static char *session_id_str;
40 37
41/** 38static struct GNUNET_TIME_Relative conclude_timeout;
42 * File handle to STDIN
43 */
44static struct GNUNET_DISK_FileHandle *stdin_fh;
45 39
46/** 40static struct GNUNET_CONSENSUS_Handle **consensus_handles;
47 * Task for reading from stdin 41
48 */ 42static unsigned int num_connected_handles;
49static GNUNET_SCHEDULER_TaskIdentifier stdin_tid = GNUNET_SCHEDULER_NO_TASK; 43
44static struct GNUNET_TESTBED_Peer **peers;
45
46static struct GNUNET_PeerIdentity *peer_ids;
50 47
48static unsigned int num_retrieved_peer_ids;
51 49
50static struct GNUNET_HashCode session_id;
51
52
53/**
54 * Signature of the event handler function called by the
55 * respective event controller.
56 *
57 * @param cls closure
58 * @param event information about the event
59 */
52static void 60static void
53stdin_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); 61controller_cb(void *cls,
62 const struct GNUNET_TESTBED_EventInformation *event)
63{
64 GNUNET_assert (0);
65}
54 66
55 67
56/** 68/**
57 * Called when a conclusion was successful. 69 * Called when a conclusion was successful.
58 * 70 *
59 * @param cls 71 * @param cls
60 * @param num_peers_in_consensus 72 * @param group
61 * @param peers_in_consensus 73 * @return GNUNET_YES if more consensus groups should be offered, GNUNET_NO if not
62 */ 74 */
75static int
76conclude_cb (void *cls, const struct GNUNET_CONSENSUS_Group *group)
77{
78 return GNUNET_NO;
79}
80
81
82
63static void 83static void
64conclude_cb (void *cls, 84generate_indices (int *indices)
65 unsigned int consensus_group_count,
66 const struct GNUNET_CONSENSUS_Group *groups)
67{ 85{
68 printf("reached conclusion\n"); 86 int j;
69 GNUNET_SCHEDULER_shutdown (); 87 j = 0;
88 while (j < replication)
89 {
90 int n;
91 int k;
92 int repeat;
93 n = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, num_peers);
94 repeat = GNUNET_NO;
95 for (k = 0; k < j; k++)
96 if (indices[k] == n)
97 {
98 repeat = GNUNET_YES;
99 break;
100 }
101 if (GNUNET_NO == repeat)
102 indices[j++] = n;
103 }
70} 104}
71 105
72 106
73static void 107static void
74insert_done_cb (void *cls, 108do_consensus ()
75 int success)
76{ 109{
77 struct GNUNET_CONSENSUS_Element *element = cls; 110 int unique_indices[replication];
111 int i;
78 112
79 GNUNET_free (element); 113 for (i = 0; i < num_values; i++)
80 if (GNUNET_YES != success)
81 { 114 {
82 printf ("insert failed\n"); 115 int j;
83 GNUNET_SCHEDULER_shutdown (); 116 struct GNUNET_HashCode *val;
84 return; 117 struct GNUNET_CONSENSUS_Element *element;
118 generate_indices(unique_indices);
119
120 val = GNUNET_malloc (sizeof *val);
121 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, val);
122
123 element = GNUNET_malloc (sizeof *element);
124 element->data = val;
125 element->size = sizeof *val;
126
127 for (j = 0; j < replication; j++)
128 {
129 int cid;
130 cid = unique_indices[j];
131 GNUNET_CONSENSUS_insert (consensus_handles[cid], element, NULL, NULL);
132 }
85 } 133 }
86 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == stdin_tid); 134
87 stdin_tid = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, stdin_fh, 135 for (i = 0; i < num_peers; i++)
88 &stdin_cb, NULL); 136 GNUNET_CONSENSUS_conclude (consensus_handles[i], conclude_timeout, 0, conclude_cb, consensus_handles[i]);
89} 137}
90 138
91 139
92/** 140/**
93 * Called whenever we can read stdin non-blocking 141 * Callback to be called when a service connect operation is completed
94 * 142 *
95 * @param cls unused 143 * @param cls the callback closure from functions generating an operation
96 * @param tc scheduler context 144 * @param op the operation that has been finished
145 * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter()
146 * @param emsg error message in case the operation has failed; will be NULL if
147 * operation has executed successfully.
97 */ 148 */
98static void 149static void
99stdin_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 150connect_complete (void *cls,
151 struct GNUNET_TESTBED_Operation *op,
152 void *ca_result,
153 const char *emsg)
100{ 154{
101 char buf[1024]; 155 struct GNUNET_CONSENSUS_Handle **chp;
102 char *ret; 156
103 struct GNUNET_CONSENSUS_Element *element; 157 if (NULL != emsg)
104
105 stdin_tid = GNUNET_SCHEDULER_NO_TASK;
106 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
107 return; /* we're done here */
108 ret = fgets (buf, 1024, stdin);
109 if (NULL == ret)
110 { 158 {
111 if (feof (stdin)) 159 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "testbed connect emsg: %s\n", emsg);
112 { 160 GNUNET_assert (0);
113 printf ("concluding ...\n");
114 GNUNET_CONSENSUS_conclude (consensus, GNUNET_TIME_UNIT_FOREVER_REL, 0, conclude_cb, NULL);
115 }
116 return;
117 } 161 }
118 162
119 printf("read: %s", buf); 163 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "connect complete\n");
164
165 chp = (struct GNUNET_CONSENSUS_Handle **) cls;
166 *chp = (struct GNUNET_CONSENSUS_Handle *) ca_result;
167 num_connected_handles++;
120 168
121 element = GNUNET_malloc (sizeof (struct GNUNET_CONSENSUS_Element) + strlen(buf) + 1); 169 if (num_connected_handles == num_peers)
122 element->type = 0; 170 {
123 element->size = strlen(buf) + 1; 171 do_consensus ();
124 element->data = &element[1]; 172 }
125 strcpy ((char *) &element[1], buf); 173}
126 GNUNET_CONSENSUS_insert (consensus, element, &insert_done_cb, element); 174
175
176static int
177new_element_cb (void *cls,
178 struct GNUNET_CONSENSUS_Element *element)
179{
180 return GNUNET_YES;
127} 181}
128 182
129 183
130/** 184/**
131 * Called when a new element was received from another peer, or an error occured. 185 * Adapter function called to establish a connection to
132 * 186 * a service.
133 * May deliver duplicate values.
134 *
135 * Elements given to a consensus operation by the local peer are NOT given
136 * to this callback.
137 * 187 *
138 * @param cls closure 188 * @param cls closure
139 * @param element new element, NULL on error 189 * @param cfg configuration of the peer to connect to; will be available until
140 * @return GNUNET_OK if the valid is well-formed and should be added to the consensus, 190 * GNUNET_TESTBED_operation_done() is called on the operation returned
141 * GNUNET_SYSERR if the element should be ignored and not be propagated 191 * from GNUNET_TESTBED_service_connect()
192 * @return service handle to return in 'op_result', NULL on error
142 */ 193 */
143static int 194static void *
144cb (void *cls, 195connect_adapter (void *cls,
145 struct GNUNET_CONSENSUS_Element *element) 196 const struct GNUNET_CONFIGURATION_Handle *cfg)
146{ 197{
147 if (NULL == element) 198 struct GNUNET_CONSENSUS_Handle *consensus;
148 { 199 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "connect adapter, %d peers\n", num_peers);
149 printf("error receiving from consensus\n"); 200 consensus = GNUNET_CONSENSUS_create (cfg, num_peers, peer_ids, &session_id, new_element_cb, NULL);
150 GNUNET_SCHEDULER_shutdown (); 201 GNUNET_assert (NULL != consensus);
151 return GNUNET_NO; 202 return consensus;
152 }
153 printf("got element\n");
154 return GNUNET_YES;
155} 203}
156 204
157 205
158/** 206/**
159 * Function run on shutdown to clean up. 207 * Adapter function called to destroy a connection to
208 * a service.
160 * 209 *
161 * @param cls the statistics handle 210 * @param cls closure
162 * @param tc scheduler context 211 * @param op_result service handle returned from the connect adapter
163 */ 212 */
164static void 213static void
165shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 214disconnect_adapter(void *cls, void *op_result)
166{ 215{
167 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "shutting down\n"); 216 /* FIXME: what to do here? */
168 if (NULL != consensus)
169 {
170 GNUNET_CONSENSUS_destroy (consensus);
171 consensus = NULL;
172 }
173} 217}
174 218
175 219
220/**
221 * Callback to be called when the requested peer information is available
222 *
223 * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information()
224 * @param op the operation this callback corresponds to
225 * @param pinfo the result; will be NULL if the operation has failed
226 * @param emsg error message if the operation has failed; will be NULL if the
227 * operation is successfull
228 */
176static void 229static void
177run (void *cls, char *const *args, const char *cfgfile, 230peer_info_cb (void *cb_cls,
178 const struct GNUNET_CONFIGURATION_Handle *cfg) 231 struct GNUNET_TESTBED_Operation *op,
232 const struct GNUNET_TESTBED_PeerInformation *pinfo,
233 const char *emsg)
179{ 234{
180 struct GNUNET_HashCode sid; 235 struct GNUNET_PeerIdentity *p;
181 struct GNUNET_PeerIdentity *pids;
182 int count;
183 int i; 236 int i;
184 237
185 if (NULL == session_id_str) 238 GNUNET_assert (NULL == emsg);
186 {
187 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "no session id given (missing -s/--session-id)\n");
188 return;
189 }
190 239
191 GNUNET_CRYPTO_hash (session_id_str, strlen (session_id_str), &sid); 240 p = (struct GNUNET_PeerIdentity *) cb_cls;
192 241
193 for (count = 0; NULL != args[count]; count++); 242 if (pinfo->pit == GNUNET_TESTBED_PIT_IDENTITY)
194 243 {
195 if (0 != count) 244 *p = *pinfo->result.id;
196 { 245 num_retrieved_peer_ids++;
197 pids = GNUNET_malloc (count * sizeof (struct GNUNET_PeerIdentity)); 246 if (num_retrieved_peer_ids == num_peers)
247 for (i = 0; i < num_peers; i++)
248 GNUNET_TESTBED_service_connect (NULL, peers[i], "consensus", connect_complete, &consensus_handles[i],
249 connect_adapter, disconnect_adapter, NULL);
198 } 250 }
199 else 251 else
200 { 252 {
201 pids = NULL; 253 GNUNET_assert (0);
202 } 254 }
255}
203 256
204 for (i = 0; i < count; i++)
205 {
206 int ret;
207 ret = GNUNET_CRYPTO_hash_from_string (args[i], &pids[i].hashPubKey);
208 if (GNUNET_OK != ret)
209 {
210 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "peer identity '%s' is malformed\n", args[i]);
211 return;
212 }
213 }
214 257
215 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, 258static void
216 &shutdown_task, NULL); 259test_master (void *cls,
217 260 unsigned int num_peers,
218 consensus = 261 struct GNUNET_TESTBED_Peer **started_peers)
219 GNUNET_CONSENSUS_create (cfg, 262{
220 count, pids, 263 int i;
221 &sid, 264
222 &cb, NULL); 265
223 266 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "test master\n");
224 stdin_fh = GNUNET_DISK_get_handle_from_native (stdin); 267
225 stdin_tid = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, stdin_fh, 268 peers = started_peers;
226 &stdin_cb, NULL); 269
270 peer_ids = GNUNET_malloc (num_peers * sizeof (struct GNUNET_PeerIdentity));
271
272 consensus_handles = GNUNET_malloc (num_peers * sizeof (struct ConsensusHandle *));
273
274 for (i = 0; i < num_peers; i++)
275 GNUNET_TESTBED_peer_get_information (peers[i],
276 GNUNET_TESTBED_PIT_IDENTITY,
277 peer_info_cb,
278 &peer_ids[i]);
279}
280
281static void
282run (void *cls, char *const *args, const char *cfgfile,
283 const struct GNUNET_CONFIGURATION_Handle *cfg)
284{
285 static char *session_str = "gnunet-consensus/test";
286
287
288 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "running gnunet-consensus\n");
289
290 GNUNET_CRYPTO_hash (session_str, strlen(session_str), &session_id);
291
292 (void) GNUNET_TESTBED_test_run ("gnunet-consensus",
293 cfgfile,
294 num_peers,
295 0,
296 controller_cb,
297 NULL,
298 test_master,
299 NULL);
227} 300}
228 301
229 302
@@ -231,13 +304,24 @@ int
231main (int argc, char **argv) 304main (int argc, char **argv)
232{ 305{
233 static const struct GNUNET_GETOPT_CommandLineOption options[] = { 306 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
234 { 's', "session-id", "ID", 307 { 'n', "num-peers", NULL,
235 gettext_noop ("session identifier"), 308 gettext_noop ("number of peers in consensus"),
236 GNUNET_YES, &GNUNET_GETOPT_set_string, &session_id_str }, 309 GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_peers },
237 GNUNET_GETOPT_OPTION_END 310 { 'k', "value-replication", NULL,
238 }; 311 gettext_noop ("how many peers receive one value?"),
239 GNUNET_PROGRAM_run (argc, argv, "gnunet-consensus", 312 GNUNET_YES, &GNUNET_GETOPT_set_uint, &replication },
313 { 'x', "num-values", NULL,
314 gettext_noop ("number of values"),
315 GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_values },
316 { 't', "timeout", NULL,
317 gettext_noop ("consensus timeout"),
318 GNUNET_YES, &GNUNET_GETOPT_set_relative_time, &conclude_timeout },
319 GNUNET_GETOPT_OPTION_END
320 };
321 conclude_timeout = GNUNET_TIME_UNIT_SECONDS;
322 GNUNET_PROGRAM_run2 (argc, argv, "gnunet-consensus",
240 "help", 323 "help",
241 options, &run, NULL); 324 options, &run, NULL, GNUNET_YES);
242 return 0; 325 return 0;
243} 326}
327