aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2013-07-23 17:26:35 +0000
committerFlorian Dold <florian.dold@gmail.com>2013-07-23 17:26:35 +0000
commit18bc05a535be767b07473e29ac85cebe79ce83cf (patch)
treee17580c67403eb892e4e0e868035b16356eed0ab
parent2584d09e42fcd0f8199b905ca5a43809bbc42aaa (diff)
downloadgnunet-18bc05a535be767b07473e29ac85cebe79ce83cf.tar.gz
gnunet-18bc05a535be767b07473e29ac85cebe79ce83cf.zip
- set iteration
-rw-r--r--src/set/gnunet-service-set.c28
-rw-r--r--src/set/gnunet-service-set.h14
-rw-r--r--src/set/gnunet-service-set_union.c50
-rw-r--r--src/set/set.h15
-rw-r--r--src/set/set_api.c87
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 */
464static void
465handle_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 */
178typedef 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 */
1434static int
1435send_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 */
1460static void
1461union_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
1424const struct SetVT * 1471const 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
214struct 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
215GNUNET_NETWORK_STRUCT_END 230GNUNET_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 */
190static void
191handle_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 */
213static void
214handle_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 */
694int
695GNUNET_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