diff options
author | Florian Dold <florian.dold@gmail.com> | 2013-07-23 17:26:35 +0000 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2013-07-23 17:26:35 +0000 |
commit | 18bc05a535be767b07473e29ac85cebe79ce83cf (patch) | |
tree | e17580c67403eb892e4e0e868035b16356eed0ab | |
parent | 2584d09e42fcd0f8199b905ca5a43809bbc42aaa (diff) | |
download | gnunet-18bc05a535be767b07473e29ac85cebe79ce83cf.tar.gz gnunet-18bc05a535be767b07473e29ac85cebe79ce83cf.zip |
- set iteration
-rw-r--r-- | src/set/gnunet-service-set.c | 28 | ||||
-rw-r--r-- | src/set/gnunet-service-set.h | 14 | ||||
-rw-r--r-- | src/set/gnunet-service-set_union.c | 50 | ||||
-rw-r--r-- | src/set/set.h | 15 | ||||
-rw-r--r-- | src/set/set_api.c | 87 |
5 files changed, 193 insertions, 1 deletions
diff --git a/src/set/gnunet-service-set.c b/src/set/gnunet-service-set.c index a55c2188e..8445b3799 100644 --- a/src/set/gnunet-service-set.c +++ b/src/set/gnunet-service-set.c | |||
@@ -455,6 +455,32 @@ handle_incoming_msg (struct OperationState *op, | |||
455 | 455 | ||
456 | 456 | ||
457 | /** | 457 | /** |
458 | * Called when a client wants to iterate the elements of a set. | ||
459 | * | ||
460 | * @param cls unused | ||
461 | * @param client client that sent the message | ||
462 | * @param m message sent by the client | ||
463 | */ | ||
464 | static void | ||
465 | handle_client_iterate (void *cls, | ||
466 | struct GNUNET_SERVER_Client *client, | ||
467 | const struct GNUNET_MessageHeader *m) | ||
468 | { | ||
469 | struct Set *set; | ||
470 | |||
471 | set = set_get (client); | ||
472 | if (NULL == set) | ||
473 | { | ||
474 | GNUNET_break (0); | ||
475 | GNUNET_SERVER_client_disconnect (client); | ||
476 | return; | ||
477 | } | ||
478 | |||
479 | set->vt->iterate (set); | ||
480 | } | ||
481 | |||
482 | |||
483 | /** | ||
458 | * Called when a client wants to create a new set. | 484 | * Called when a client wants to create a new set. |
459 | * | 485 | * |
460 | * @param cls unused | 486 | * @param cls unused |
@@ -939,6 +965,8 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, | |||
939 | {handle_client_add_remove, NULL, GNUNET_MESSAGE_TYPE_SET_ADD, 0}, | 965 | {handle_client_add_remove, NULL, GNUNET_MESSAGE_TYPE_SET_ADD, 0}, |
940 | {handle_client_create, NULL, GNUNET_MESSAGE_TYPE_SET_CREATE, | 966 | {handle_client_create, NULL, GNUNET_MESSAGE_TYPE_SET_CREATE, |
941 | sizeof (struct GNUNET_SET_CreateMessage)}, | 967 | sizeof (struct GNUNET_SET_CreateMessage)}, |
968 | {handle_client_iterate, NULL, GNUNET_MESSAGE_TYPE_SET_ITER_REQUEST, | ||
969 | sizeof (struct GNUNET_MessageHeader)}, | ||
942 | {handle_client_evaluate, NULL, GNUNET_MESSAGE_TYPE_SET_EVALUATE, 0}, | 970 | {handle_client_evaluate, NULL, GNUNET_MESSAGE_TYPE_SET_EVALUATE, 0}, |
943 | {handle_client_listen, NULL, GNUNET_MESSAGE_TYPE_SET_LISTEN, | 971 | {handle_client_listen, NULL, GNUNET_MESSAGE_TYPE_SET_LISTEN, |
944 | sizeof (struct GNUNET_SET_ListenMessage)}, | 972 | sizeof (struct GNUNET_SET_ListenMessage)}, |
diff --git a/src/set/gnunet-service-set.h b/src/set/gnunet-service-set.h index 6ababe92f..c93cc660a 100644 --- a/src/set/gnunet-service-set.h +++ b/src/set/gnunet-service-set.h | |||
@@ -170,6 +170,15 @@ typedef void (*CancelImpl) (struct SetState *set, | |||
170 | 170 | ||
171 | 171 | ||
172 | /** | 172 | /** |
173 | * Signature of functions that implement sending all the set's | ||
174 | * elements to the client. | ||
175 | * | ||
176 | * @param set set that should be iterated over | ||
177 | */ | ||
178 | typedef void (*IterateImpl) (struct Set *set); | ||
179 | |||
180 | |||
181 | /** | ||
173 | * Dispatch table for a specific set operation. | 182 | * Dispatch table for a specific set operation. |
174 | * Every set operation has to implement the callback | 183 | * Every set operation has to implement the callback |
175 | * in this struct. | 184 | * in this struct. |
@@ -222,6 +231,11 @@ struct SetVT | |||
222 | * its ID. | 231 | * its ID. |
223 | */ | 232 | */ |
224 | CancelImpl cancel; | 233 | CancelImpl cancel; |
234 | |||
235 | /** | ||
236 | * Callback for iterating over all set elements. | ||
237 | */ | ||
238 | IterateImpl iterate; | ||
225 | }; | 239 | }; |
226 | 240 | ||
227 | 241 | ||
diff --git a/src/set/gnunet-service-set_union.c b/src/set/gnunet-service-set_union.c index e512761cc..87100bf54 100644 --- a/src/set/gnunet-service-set_union.c +++ b/src/set/gnunet-service-set_union.c | |||
@@ -1421,6 +1421,53 @@ union_op_cancel (struct SetState *set_state, uint32_t op_id) | |||
1421 | } | 1421 | } |
1422 | 1422 | ||
1423 | 1423 | ||
1424 | /** | ||
1425 | * Iterator over hash map entries. | ||
1426 | * | ||
1427 | * @param cls closure | ||
1428 | * @param key current key code | ||
1429 | * @param value value in the hash map | ||
1430 | * @return GNUNET_YES if we should continue to | ||
1431 | * iterate, | ||
1432 | * GNUNET_NO if not. | ||
1433 | */ | ||
1434 | static int | ||
1435 | send_iter_element_iter (void *cls, | ||
1436 | const struct GNUNET_HashCode *key, | ||
1437 | void *value) | ||
1438 | { | ||
1439 | struct ElementEntry *ee = value; | ||
1440 | struct Set *set = cls; | ||
1441 | struct GNUNET_SET_IterResponseMessage *m; | ||
1442 | struct GNUNET_MQ_Envelope *ev; | ||
1443 | |||
1444 | ev = GNUNET_MQ_msg_extra (m, ee->element.size, | ||
1445 | GNUNET_MESSAGE_TYPE_SET_ITER_ELEMENT); | ||
1446 | |||
1447 | m->element_type = ee->element.type; | ||
1448 | memcpy (&m[1], ee->element.data, ee->element.size); | ||
1449 | GNUNET_MQ_send (set->client_mq, ev); | ||
1450 | |||
1451 | return GNUNET_YES; | ||
1452 | } | ||
1453 | |||
1454 | |||
1455 | /** | ||
1456 | * Send all elements of the union set to the client. | ||
1457 | * | ||
1458 | * @param set set to iterate over | ||
1459 | */ | ||
1460 | static void | ||
1461 | union_iterate (struct Set *set) | ||
1462 | { | ||
1463 | struct GNUNET_MQ_Envelope *ev; | ||
1464 | |||
1465 | GNUNET_CONTAINER_multihashmap_iterate (set->state->elements, send_iter_element_iter, set); | ||
1466 | ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_ITER_DONE); | ||
1467 | GNUNET_MQ_send (set->client_mq, ev); | ||
1468 | } | ||
1469 | |||
1470 | |||
1424 | const struct SetVT * | 1471 | const struct SetVT * |
1425 | _GSS_union_vt () | 1472 | _GSS_union_vt () |
1426 | { | 1473 | { |
@@ -1433,7 +1480,8 @@ _GSS_union_vt () | |||
1433 | .evaluate = &union_evaluate, | 1480 | .evaluate = &union_evaluate, |
1434 | .accept = &union_accept, | 1481 | .accept = &union_accept, |
1435 | .peer_disconnect = &union_peer_disconnect, | 1482 | .peer_disconnect = &union_peer_disconnect, |
1436 | .cancel = &union_op_cancel | 1483 | .cancel = &union_op_cancel, |
1484 | .iterate = &union_iterate | ||
1437 | }; | 1485 | }; |
1438 | 1486 | ||
1439 | return &union_vt; | 1487 | return &union_vt; |
diff --git a/src/set/set.h b/src/set/set.h index fc29e6696..9f6eb3642 100644 --- a/src/set/set.h +++ b/src/set/set.h | |||
@@ -211,6 +211,21 @@ struct GNUNET_SET_CancelMessage | |||
211 | uint32_t request_id GNUNET_PACKED; | 211 | uint32_t request_id GNUNET_PACKED; |
212 | }; | 212 | }; |
213 | 213 | ||
214 | struct GNUNET_SET_IterResponseMessage | ||
215 | { | ||
216 | /** | ||
217 | * Type: GNUNET_MESSAGE_TYPE_SET_ITER_RESPONSE | ||
218 | */ | ||
219 | struct GNUNET_MessageHeader header; | ||
220 | |||
221 | /** | ||
222 | * Type of the element attachted to the message, | ||
223 | * if any. | ||
224 | */ | ||
225 | uint16_t element_type GNUNET_PACKED; | ||
226 | |||
227 | /* rest: element */ | ||
228 | }; | ||
214 | 229 | ||
215 | GNUNET_NETWORK_STRUCT_END | 230 | GNUNET_NETWORK_STRUCT_END |
216 | 231 | ||
diff --git a/src/set/set_api.c b/src/set/set_api.c index 88f334cbc..c2e88e65f 100644 --- a/src/set/set_api.c +++ b/src/set/set_api.c | |||
@@ -67,6 +67,17 @@ struct GNUNET_SET_Handle | |||
67 | * Has the set become invalid (e.g. service died)? | 67 | * Has the set become invalid (e.g. service died)? |
68 | */ | 68 | */ |
69 | int invalid; | 69 | int invalid; |
70 | |||
71 | /** | ||
72 | * Callback for the current iteration over the set, | ||
73 | * NULL if no iterator is active. | ||
74 | */ | ||
75 | GNUNET_SET_ElementIterator iterator; | ||
76 | |||
77 | /** | ||
78 | * Closure for 'iterator' | ||
79 | */ | ||
80 | void *iterator_cls; | ||
70 | }; | 81 | }; |
71 | 82 | ||
72 | 83 | ||
@@ -171,6 +182,47 @@ struct GNUNET_SET_ListenHandle | |||
171 | 182 | ||
172 | 183 | ||
173 | /** | 184 | /** |
185 | * Handle element for iteration over the set. | ||
186 | * | ||
187 | * @param cls the set | ||
188 | * @param mh the message | ||
189 | */ | ||
190 | static void | ||
191 | handle_iter_element (void *cls, const struct GNUNET_MessageHeader *mh) | ||
192 | { | ||
193 | struct GNUNET_SET_Handle *set = cls; | ||
194 | struct GNUNET_SET_Element element; | ||
195 | const struct GNUNET_SET_IterResponseMessage *msg = | ||
196 | (const struct GNUNET_SET_IterResponseMessage *) mh; | ||
197 | |||
198 | if (NULL == set->iterator) | ||
199 | return; | ||
200 | |||
201 | element.type = htons (mh->type); | ||
202 | element.data = &msg[1]; | ||
203 | set->iterator (set->iterator_cls, &element); | ||
204 | } | ||
205 | |||
206 | |||
207 | /** | ||
208 | * Handle element for iteration over the set. | ||
209 | * | ||
210 | * @param cls the set | ||
211 | * @param mh the message | ||
212 | */ | ||
213 | static void | ||
214 | handle_iter_done (void *cls, const struct GNUNET_MessageHeader *mh) | ||
215 | { | ||
216 | struct GNUNET_SET_Handle *set = cls; | ||
217 | |||
218 | if (NULL == set->iterator) | ||
219 | return; | ||
220 | |||
221 | set->iterator (set->iterator_cls, NULL); | ||
222 | } | ||
223 | |||
224 | |||
225 | /** | ||
174 | * Handle result message for a set operation. | 226 | * Handle result message for a set operation. |
175 | * | 227 | * |
176 | * @param cls the set | 228 | * @param cls the set |
@@ -302,6 +354,8 @@ GNUNET_SET_create (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
302 | struct GNUNET_SET_CreateMessage *msg; | 354 | struct GNUNET_SET_CreateMessage *msg; |
303 | static const struct GNUNET_MQ_MessageHandler mq_handlers[] = { | 355 | static const struct GNUNET_MQ_MessageHandler mq_handlers[] = { |
304 | {handle_result, GNUNET_MESSAGE_TYPE_SET_RESULT, 0}, | 356 | {handle_result, GNUNET_MESSAGE_TYPE_SET_RESULT, 0}, |
357 | {handle_iter_element, GNUNET_MESSAGE_TYPE_SET_ITER_ELEMENT, 0}, | ||
358 | {handle_iter_done, GNUNET_MESSAGE_TYPE_SET_ITER_DONE, 0}, | ||
305 | GNUNET_MQ_HANDLERS_END | 359 | GNUNET_MQ_HANDLERS_END |
306 | }; | 360 | }; |
307 | 361 | ||
@@ -623,3 +677,36 @@ GNUNET_SET_commit (struct GNUNET_SET_OperationHandle *oh, | |||
623 | return GNUNET_OK; | 677 | return GNUNET_OK; |
624 | } | 678 | } |
625 | 679 | ||
680 | |||
681 | |||
682 | /** | ||
683 | * Iterate over all elements in the given set. | ||
684 | * Note that this operation involves transferring every element of the set | ||
685 | * from the service to the client, and is thus costly. | ||
686 | * | ||
687 | * @param set the set to iterate over | ||
688 | * @param iter the iterator to call for each element | ||
689 | * @param cls closure for 'iter' | ||
690 | * @return GNUNET_YES if the iteration started successfuly, | ||
691 | * GNUNET_NO if another iteration is active | ||
692 | * GNUNET_SYSERR if the set is invalid (e.g. the server crashed, disconnected) | ||
693 | */ | ||
694 | int | ||
695 | GNUNET_SET_iterate (struct GNUNET_SET_Handle *set, GNUNET_SET_ElementIterator iter, void *cls) | ||
696 | { | ||
697 | struct GNUNET_MQ_Envelope *ev; | ||
698 | |||
699 | GNUNET_assert (NULL != iter); | ||
700 | |||
701 | if (GNUNET_YES == set->invalid) | ||
702 | return GNUNET_SYSERR; | ||
703 | if (NULL != set->iterator) | ||
704 | return GNUNET_NO; | ||
705 | |||
706 | set->iterator = iter; | ||
707 | set->iterator_cls = cls; | ||
708 | ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_ITER_REQUEST); | ||
709 | GNUNET_MQ_send (set->mq, ev); | ||
710 | return GNUNET_YES; | ||
711 | } | ||
712 | |||