aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2013-08-12 18:00:43 +0000
committerFlorian Dold <florian.dold@gmail.com>2013-08-12 18:00:43 +0000
commit566dfe32be22ed1f071b974be3c4dd8bc5721151 (patch)
treedc4e89e80aab53e1cb69604c2960eaaf5043bb17 /src
parentd734cfd6677de174aa51a07437b0e0cae4c870be (diff)
downloadgnunet-566dfe32be22ed1f071b974be3c4dd8bc5721151.tar.gz
gnunet-566dfe32be22ed1f071b974be3c4dd8bc5721151.zip
- correct iteraion in multihashmap
- iterate over elements with client ack in set
Diffstat (limited to 'src')
-rw-r--r--src/include/gnunet_protocols.h4
-rw-r--r--src/set/gnunet-service-set.c141
-rw-r--r--src/set/gnunet-service-set.h70
-rw-r--r--src/set/gnunet-service-set_union.c216
-rw-r--r--src/set/set.h13
-rw-r--r--src/set/set_api.c5
-rw-r--r--src/set/test_set.conf2
-rw-r--r--src/set/test_set_api.c47
-rw-r--r--src/util/container_multihashmap.c4
9 files changed, 291 insertions, 211 deletions
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index ba34af814..06703abe9 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -1690,9 +1690,9 @@ extern "C"
1690#define GNUNET_MESSAGE_TYPE_SET_CANCEL 570 1690#define GNUNET_MESSAGE_TYPE_SET_CANCEL 570
1691 1691
1692/** 1692/**
1693 * Acknowledge results 1693 * Acknowledge result from iteration
1694 */ 1694 */
1695#define GNUNET_MESSAGE_TYPE_SET_ACK 571 1695#define GNUNET_MESSAGE_TYPE_SET_ITER_ACK 571
1696 1696
1697/** 1697/**
1698 * Create an empty set 1698 * Create an empty set
diff --git a/src/set/gnunet-service-set.c b/src/set/gnunet-service-set.c
index cfa0ab711..9210e1ea8 100644
--- a/src/set/gnunet-service-set.c
+++ b/src/set/gnunet-service-set.c
@@ -261,6 +261,28 @@ listener_destroy (struct Listener *listener)
261 261
262 262
263/** 263/**
264 * Iterator over hash map entries.
265 *
266 * @param cls closure
267 * @param key current key code
268 * @param value value in the hash map
269 * @return GNUNET_YES if we should continue to
270 * iterate,
271 * GNUNET_NO if not.
272 */
273static int
274destroy_elements_iterator (void *cls,
275 const struct GNUNET_HashCode * key,
276 void *value)
277{
278 struct ElementEntry *ee = value;
279
280 GNUNET_free (ee);
281 return GNUNET_YES;
282}
283
284
285/**
264 * Destroy a set, and free all resources associated with it. 286 * Destroy a set, and free all resources associated with it.
265 * 287 *
266 * @param set the set to destroy 288 * @param set the set to destroy
@@ -282,6 +304,18 @@ set_destroy (struct Set *set)
282 GNUNET_MQ_destroy (set->client_mq); 304 GNUNET_MQ_destroy (set->client_mq);
283 set->client_mq = NULL; 305 set->client_mq = NULL;
284 } 306 }
307 if (NULL != set->elements)
308 {
309 GNUNET_CONTAINER_multihashmap_iterate (set->elements,
310 destroy_elements_iterator, NULL);
311 GNUNET_CONTAINER_multihashmap_destroy (set->elements);
312 set->elements = NULL;
313 }
314 if (NULL != set->iter)
315 {
316 GNUNET_CONTAINER_multihashmap_iterator_destroy (set->iter);
317 set->iter = NULL;
318 }
285 GNUNET_assert (NULL != set->state); 319 GNUNET_assert (NULL != set->state);
286 set->vt->destroy_set (set->state); 320 set->vt->destroy_set (set->state);
287 set->state = NULL; 321 set->state = NULL;
@@ -455,6 +489,32 @@ handle_incoming_msg (struct OperationState *op,
455} 489}
456 490
457 491
492static void
493send_client_element (struct Set *set)
494{
495 int ret;
496 struct ElementEntry *ee;
497 struct GNUNET_MQ_Envelope *ev;
498
499 GNUNET_assert (NULL != set->iter);
500 ret = GNUNET_CONTAINER_multihashmap_iterator_next (set->iter, NULL, (const void **) &ee);
501 if (GNUNET_NO == ret)
502 {
503 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_ITER_DONE);
504 }
505 else
506 {
507 struct GNUNET_SET_IterResponseMessage *msg;
508
509 GNUNET_assert (NULL != ee);
510 ev = GNUNET_MQ_msg_extra (msg, ee->element.size, GNUNET_MESSAGE_TYPE_SET_ITER_ELEMENT);
511 memcpy (&msg[1], ee->element.data, ee->element.size);
512 msg->element_type = ee->element.type;
513 }
514 GNUNET_MQ_send (set->client_mq, ev);
515}
516
517
458/** 518/**
459 * Called when a client wants to iterate the elements of a set. 519 * Called when a client wants to iterate the elements of a set.
460 * 520 *
@@ -477,8 +537,17 @@ handle_client_iterate (void *cls,
477 return; 537 return;
478 } 538 }
479 539
540 if (NULL != set->iter)
541 {
542 GNUNET_break (0);
543 GNUNET_SERVER_client_disconnect (client);
544 return;
545 }
546 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "iterating union set with %u elements\n",
547 GNUNET_CONTAINER_multihashmap_size (set->elements));
480 GNUNET_SERVER_receive_done (client, GNUNET_OK); 548 GNUNET_SERVER_receive_done (client, GNUNET_OK);
481 set->vt->iterate (set); 549 set->iter = GNUNET_CONTAINER_multihashmap_iterator_create (set->elements);
550 send_client_element (set);
482} 551}
483 552
484 553
@@ -525,6 +594,7 @@ handle_client_create (void *cls,
525 } 594 }
526 595
527 set->state = set->vt->create (); 596 set->state = set->vt->create ();
597 set->elements = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
528 set->client = client; 598 set->client = client;
529 set->client_mq = GNUNET_MQ_queue_for_server_client (client); 599 set->client_mq = GNUNET_MQ_queue_for_server_client (client);
530 GNUNET_CONTAINER_DLL_insert (sets_head, sets_tail, set); 600 GNUNET_CONTAINER_DLL_insert (sets_head, sets_tail, set);
@@ -633,6 +703,7 @@ handle_client_add_remove (void *cls,
633 struct Set *set; 703 struct Set *set;
634 const struct GNUNET_SET_ElementMessage *msg; 704 const struct GNUNET_SET_ElementMessage *msg;
635 struct GNUNET_SET_Element el; 705 struct GNUNET_SET_Element el;
706 struct ElementEntry *ee;
636 707
637 set = set_get (client); 708 set = set_get (client);
638 if (NULL == set) 709 if (NULL == set)
@@ -641,16 +712,55 @@ handle_client_add_remove (void *cls,
641 GNUNET_SERVER_client_disconnect (client); 712 GNUNET_SERVER_client_disconnect (client);
642 return; 713 return;
643 } 714 }
715 GNUNET_SERVER_receive_done (client, GNUNET_OK);
644 msg = (const struct GNUNET_SET_ElementMessage *) m; 716 msg = (const struct GNUNET_SET_ElementMessage *) m;
645 el.size = ntohs (m->size) - sizeof *msg; 717 el.size = ntohs (m->size) - sizeof *msg;
646 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 718 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
647 "client ins/rem element of size %u\n", el.size); 719 "client ins/rem element of size %u\n", el.size);
648 el.data = &msg[1]; 720 el.data = &msg[1];
649 if (GNUNET_MESSAGE_TYPE_SET_REMOVE == ntohs (m->type)) 721 if (GNUNET_MESSAGE_TYPE_SET_REMOVE == ntohs (m->type))
650 set->vt->remove (set->state, &el); 722 {
723 struct GNUNET_HashCode hash;
724
725 GNUNET_CRYPTO_hash (el.data, el.size, &hash);
726 ee = GNUNET_CONTAINER_multihashmap_get (set->elements, &hash);
727 if (NULL == ee)
728 {
729 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "client tried to remove non-existing element\n");
730 return;
731 }
732 if (GNUNET_YES == ee->removed)
733 {
734 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "client tried to remove element twice\n");
735 return;
736 }
737 ee->removed = GNUNET_YES;
738 ee->generation_removed = set->current_generation;
739 set->vt->remove (set->state, ee);
740 }
651 else 741 else
652 set->vt->add (set->state, &el); 742 {
653 GNUNET_SERVER_receive_done (client, GNUNET_OK); 743 struct ElementEntry *ee_dup;
744
745 ee = GNUNET_malloc (el.size + sizeof *ee);
746 ee->element.size = el.size;
747 memcpy (&ee[1], el.data, el.size);
748 ee->element.data = &ee[1];
749 ee->generation_added = set->current_generation;
750 ee->remote = GNUNET_NO;
751 GNUNET_CRYPTO_hash (ee->element.data, el.size, &ee->element_hash);
752 ee_dup = GNUNET_CONTAINER_multihashmap_get (set->elements,
753 &ee->element_hash);
754 if (NULL != ee_dup)
755 {
756 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "element inserted twice, ignoring\n");
757 GNUNET_free (ee);
758 return;
759 }
760 GNUNET_CONTAINER_multihashmap_put (set->elements, &ee->element_hash, ee,
761 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
762 set->vt->add (set->state, ee);
763 }
654} 764}
655 765
656 766
@@ -712,12 +822,29 @@ handle_client_evaluate (void *cls,
712 * @param m the message 822 * @param m the message
713 */ 823 */
714static void 824static void
715handle_client_ack (void *cls, 825handle_client_iter_ack (void *cls,
716 struct GNUNET_SERVER_Client *client, 826 struct GNUNET_SERVER_Client *client,
717 const struct GNUNET_MessageHeader *m) 827 const struct GNUNET_MessageHeader *m)
718{ 828{
719 /* FIXME: implement */ 829 struct Set *set;
830
831 set = set_get (client);
832 if (NULL == set)
833 {
834 GNUNET_break (0);
835 GNUNET_SERVER_client_disconnect (client);
836 return;
837 }
838
839 if (NULL == set->iter)
840 {
841 GNUNET_break (0);
842 GNUNET_SERVER_client_disconnect (client);
843 return;
844 }
845
720 GNUNET_SERVER_receive_done (client, GNUNET_OK); 846 GNUNET_SERVER_receive_done (client, GNUNET_OK);
847 send_client_element (set);
721} 848}
722 849
723 850
@@ -976,7 +1103,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
976 static const struct GNUNET_SERVER_MessageHandler server_handlers[] = { 1103 static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
977 {handle_client_accept, NULL, GNUNET_MESSAGE_TYPE_SET_ACCEPT, 1104 {handle_client_accept, NULL, GNUNET_MESSAGE_TYPE_SET_ACCEPT,
978 sizeof (struct GNUNET_SET_AcceptRejectMessage)}, 1105 sizeof (struct GNUNET_SET_AcceptRejectMessage)},
979 {handle_client_ack, NULL, GNUNET_MESSAGE_TYPE_SET_ACK, 0}, 1106 {handle_client_iter_ack, NULL, GNUNET_MESSAGE_TYPE_SET_ITER_ACK, 0},
980 {handle_client_add_remove, NULL, GNUNET_MESSAGE_TYPE_SET_ADD, 0}, 1107 {handle_client_add_remove, NULL, GNUNET_MESSAGE_TYPE_SET_ADD, 0},
981 {handle_client_create, NULL, GNUNET_MESSAGE_TYPE_SET_CREATE, 1108 {handle_client_create, NULL, GNUNET_MESSAGE_TYPE_SET_CREATE,
982 sizeof (struct GNUNET_SET_CreateMessage)}, 1109 sizeof (struct GNUNET_SET_CreateMessage)},
diff --git a/src/set/gnunet-service-set.h b/src/set/gnunet-service-set.h
index c93cc660a..ae28b24c2 100644
--- a/src/set/gnunet-service-set.h
+++ b/src/set/gnunet-service-set.h
@@ -57,6 +57,7 @@ struct OperationState;
57/* forward declarations */ 57/* forward declarations */
58struct Set; 58struct Set;
59struct TunnelContext; 59struct TunnelContext;
60struct ElementEntry;
60 61
61 62
62/** 63/**
@@ -103,6 +104,8 @@ struct OperationSpecification
103}; 104};
104 105
105 106
107
108
106/** 109/**
107 * Signature of functions that create the implementation-specific 110 * Signature of functions that create the implementation-specific
108 * state for a set supporting a specific operation. 111 * state for a set supporting a specific operation.
@@ -119,7 +122,7 @@ typedef struct SetState *(*CreateImpl) (void);
119 * @param set implementation-specific set state 122 * @param set implementation-specific set state
120 * @param msg element message from the client 123 * @param msg element message from the client
121 */ 124 */
122typedef void (*AddRemoveImpl) (struct SetState *state, const struct GNUNET_SET_Element *element); 125typedef void (*AddRemoveImpl) (struct SetState *state, struct ElementEntry *ee);
123 126
124 127
125/** 128/**
@@ -240,6 +243,54 @@ struct SetVT
240 243
241 244
242/** 245/**
246 * Information about an element element in the set.
247 * All elements are stored in a hash-table
248 * from their hash-code to their 'struct Element',
249 * so that the remove and add operations are reasonably
250 * fast.
251 */
252struct ElementEntry
253{
254 /**
255 * The actual element. The data for the element
256 * should be allocated at the end of this struct.
257 */
258 struct GNUNET_SET_Element element;
259
260 /**
261 * Hash of the element.
262 * Will be used to derive the different IBF keys
263 * for different salts.
264 */
265 struct GNUNET_HashCode element_hash;
266
267 /**
268 * Generation the element was added by the client.
269 * Operations of earlier generations will not consider the element.
270 */
271 unsigned int generation_added;
272
273 /**
274 * GNUNET_YES if the element has been removed in some generation.
275 */
276 int removed;
277
278 /**
279 * Generation the element was removed by the client.
280 * Operations of later generations will not consider the element.
281 * Only valid if is_removed is GNUNET_YES.
282 */
283 unsigned int generation_removed;
284
285 /**
286 * GNUNET_YES if the element is a remote element, and does not belong
287 * to the operation's set.
288 */
289 int remote;
290};
291
292
293/**
243 * A set that supports a specific operation 294 * A set that supports a specific operation
244 * with other peers. 295 * with other peers.
245 */ 296 */
@@ -281,6 +332,23 @@ struct Set
281 * Implementation-specific state. 332 * Implementation-specific state.
282 */ 333 */
283 struct SetState *state; 334 struct SetState *state;
335
336 /**
337 * Current state of iterating elements for the client.
338 * NULL if we are not currently iterating.
339 */
340 struct GNUNET_CONTAINER_MultiHashMapIterator *iter;
341
342 /**
343 * Maps 'struct GNUNET_HashCode' to 'struct ElementEntry'.
344 */
345 struct GNUNET_CONTAINER_MultiHashMap *elements;
346
347 /**
348 * Current generation, that is, number of
349 * previously executed operations on this set
350 */
351 unsigned int current_generation;
284}; 352};
285 353
286 354
diff --git a/src/set/gnunet-service-set_union.c b/src/set/gnunet-service-set_union.c
index 1980cdacb..e48386492 100644
--- a/src/set/gnunet-service-set_union.c
+++ b/src/set/gnunet-service-set_union.c
@@ -167,7 +167,7 @@ struct OperationState
167 * Set state of the set that this operation 167 * Set state of the set that this operation
168 * belongs to. 168 * belongs to.
169 */ 169 */
170 struct SetState *set_state; 170 struct Set *set;
171 171
172 /** 172 /**
173 * Evaluate operations are held in 173 * Evaluate operations are held in
@@ -184,54 +184,6 @@ struct OperationState
184 184
185 185
186/** 186/**
187 * Information about an element element in the set.
188 * All elements are stored in a hash-table
189 * from their hash-code to their 'struct Element',
190 * so that the remove and add operations are reasonably
191 * fast.
192 */
193struct ElementEntry
194{
195 /**
196 * The actual element. The data for the element
197 * should be allocated at the end of this struct.
198 */
199 struct GNUNET_SET_Element element;
200
201 /**
202 * Hash of the element.
203 * Will be used to derive the different IBF keys
204 * for different salts.
205 */
206 struct GNUNET_HashCode element_hash;
207
208 /**
209 * Generation the element was added by the client.
210 * Operations of earlier generations will not consider the element.
211 */
212 unsigned int generation_added;
213
214 /**
215 * GNUNET_YES if the element has been removed in some generation.
216 */
217 int removed;
218
219 /**
220 * Generation the element was removed by the client.
221 * Operations of later generations will not consider the element.
222 * Only valid if is_removed is GNUNET_YES.
223 */
224 unsigned int generation_removed;
225
226 /**
227 * GNUNET_YES if the element is a remote element, and does not belong
228 * to the operation's set.
229 */
230 int remote;
231};
232
233
234/**
235 * The key entry is used to associate an ibf key with 187 * The key entry is used to associate an ibf key with
236 * an element. 188 * an element.
237 */ 189 */
@@ -289,11 +241,6 @@ struct SetState
289 struct StrataEstimator *se; 241 struct StrataEstimator *se;
290 242
291 /** 243 /**
292 * Maps 'struct GNUNET_HashCode' to 'struct ElementEntry'.
293 */
294 struct GNUNET_CONTAINER_MultiHashMap *elements;
295
296 /**
297 * Evaluate operations are held in 244 * Evaluate operations are held in
298 * a linked list. 245 * a linked list.
299 */ 246 */
@@ -304,38 +251,9 @@ struct SetState
304 * a linked list. 251 * a linked list.
305 */ 252 */
306 struct OperationState *ops_tail; 253 struct OperationState *ops_tail;
307
308 /**
309 * Current generation, that is, number of
310 * previously executed operations on this set
311 */
312 unsigned int current_generation;
313}; 254};
314 255
315 256
316
317/**
318 * Iterator over hash map entries.
319 *
320 * @param cls closure
321 * @param key current key code
322 * @param value value in the hash map
323 * @return GNUNET_YES if we should continue to
324 * iterate,
325 * GNUNET_NO if not.
326 */
327static int
328destroy_elements_iterator (void *cls,
329 const struct GNUNET_HashCode * key,
330 void *value)
331{
332 struct ElementEntry *ee = value;
333
334 GNUNET_free (ee);
335 return GNUNET_YES;
336}
337
338
339/** 257/**
340 * Iterator over hash map entries. 258 * Iterator over hash map entries.
341 * 259 *
@@ -378,8 +296,8 @@ static void
378union_operation_destroy (struct OperationState *eo) 296union_operation_destroy (struct OperationState *eo)
379{ 297{
380 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying union op\n"); 298 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying union op\n");
381 GNUNET_CONTAINER_DLL_remove (eo->set_state->ops_head, 299 GNUNET_CONTAINER_DLL_remove (eo->set->state->ops_head,
382 eo->set_state->ops_tail, 300 eo->set->state->ops_tail,
383 eo); 301 eo);
384 if (NULL != eo->mq) 302 if (NULL != eo->mq)
385 { 303 {
@@ -647,9 +565,9 @@ prepare_ibf (struct OperationState *eo, uint16_t size)
647 if (NULL == eo->key_to_element) 565 if (NULL == eo->key_to_element)
648 { 566 {
649 unsigned int len; 567 unsigned int len;
650 len = GNUNET_CONTAINER_multihashmap_size (eo->set_state->elements); 568 len = GNUNET_CONTAINER_multihashmap_size (eo->set->elements);
651 eo->key_to_element = GNUNET_CONTAINER_multihashmap32_create (len + 1); 569 eo->key_to_element = GNUNET_CONTAINER_multihashmap32_create (len + 1);
652 GNUNET_CONTAINER_multihashmap_iterate (eo->set_state->elements, 570 GNUNET_CONTAINER_multihashmap_iterate (eo->set->elements,
653 init_key_to_element_iterator, eo); 571 init_key_to_element_iterator, eo);
654 } 572 }
655 if (NULL != eo->local_ibf) 573 if (NULL != eo->local_ibf)
@@ -720,7 +638,7 @@ send_strata_estimator (struct OperationState *eo)
720 ev = GNUNET_MQ_msg_header_extra (strata_msg, 638 ev = GNUNET_MQ_msg_header_extra (strata_msg,
721 SE_STRATA_COUNT * IBF_BUCKET_SIZE * SE_IBF_SIZE, 639 SE_STRATA_COUNT * IBF_BUCKET_SIZE * SE_IBF_SIZE,
722 GNUNET_MESSAGE_TYPE_SET_P2P_SE); 640 GNUNET_MESSAGE_TYPE_SET_P2P_SE);
723 strata_estimator_write (eo->set_state->se, &strata_msg[1]); 641 strata_estimator_write (eo->set->state->se, &strata_msg[1]);
724 GNUNET_MQ_send (eo->mq, ev); 642 GNUNET_MQ_send (eo->mq, ev);
725 eo->phase = PHASE_EXPECT_IBF; 643 eo->phase = PHASE_EXPECT_IBF;
726 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sent SE, expecting IBF\n"); 644 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sent SE, expecting IBF\n");
@@ -1218,7 +1136,7 @@ union_evaluate (struct OperationSpecification *spec,
1218 tc->vt = _GSS_union_vt (); 1136 tc->vt = _GSS_union_vt ();
1219 tc->op = eo; 1137 tc->op = eo;
1220 eo->se = strata_estimator_dup (spec->set->state->se); 1138 eo->se = strata_estimator_dup (spec->set->state->se);
1221 eo->set_state = spec->set->state; 1139 eo->set = spec->set;
1222 eo->spec = spec; 1140 eo->spec = spec;
1223 eo->tunnel = tunnel; 1141 eo->tunnel = tunnel;
1224 eo->mq = GNUNET_MESH_mq_create (tunnel); 1142 eo->mq = GNUNET_MESH_mq_create (tunnel);
@@ -1230,8 +1148,8 @@ union_evaluate (struct OperationSpecification *spec,
1230 /* we started the operation, thus we have to send the operation request */ 1148 /* we started the operation, thus we have to send the operation request */
1231 eo->phase = PHASE_EXPECT_SE; 1149 eo->phase = PHASE_EXPECT_SE;
1232 1150
1233 GNUNET_CONTAINER_DLL_insert (eo->set_state->ops_head, 1151 GNUNET_CONTAINER_DLL_insert (eo->set->state->ops_head,
1234 eo->set_state->ops_tail, 1152 eo->set->state->ops_tail,
1235 eo); 1153 eo);
1236 1154
1237 send_operation_request (eo); 1155 send_operation_request (eo);
@@ -1259,15 +1177,15 @@ union_accept (struct OperationSpecification *spec,
1259 eo = GNUNET_new (struct OperationState); 1177 eo = GNUNET_new (struct OperationState);
1260 tc->vt = _GSS_union_vt (); 1178 tc->vt = _GSS_union_vt ();
1261 tc->op = eo; 1179 tc->op = eo;
1262 eo->set_state = spec->set->state; 1180 eo->set = spec->set;
1263 eo->generation_created = eo->set_state->current_generation++; 1181 eo->generation_created = eo->set->current_generation++;
1264 eo->spec = spec; 1182 eo->spec = spec;
1265 eo->tunnel = tunnel; 1183 eo->tunnel = tunnel;
1266 eo->mq = GNUNET_MESH_mq_create (tunnel); 1184 eo->mq = GNUNET_MESH_mq_create (tunnel);
1267 eo->se = strata_estimator_dup (eo->set_state->se); 1185 eo->se = strata_estimator_dup (eo->set->state->se);
1268 /* transfer ownership of mq and socket from incoming to eo */ 1186 /* transfer ownership of mq and socket from incoming to eo */
1269 GNUNET_CONTAINER_DLL_insert (eo->set_state->ops_head, 1187 GNUNET_CONTAINER_DLL_insert (eo->set->state->ops_head,
1270 eo->set_state->ops_tail, 1188 eo->set->state->ops_tail,
1271 eo); 1189 eo);
1272 /* kick off the operation */ 1190 /* kick off the operation */
1273 send_strata_estimator (eo); 1191 send_strata_estimator (eo);
@@ -1287,9 +1205,6 @@ union_set_create (void)
1287 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "union set created\n"); 1205 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "union set created\n");
1288 1206
1289 set_state = GNUNET_new (struct SetState); 1207 set_state = GNUNET_new (struct SetState);
1290 /* keys of the hash map are stored in the element entrys, thus we do not
1291 * want the hash map to copy them */
1292 set_state->elements = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1293 set_state->se = strata_estimator_create (SE_STRATA_COUNT, 1208 set_state->se = strata_estimator_create (SE_STRATA_COUNT,
1294 SE_IBF_SIZE, SE_IBF_HASH_NUM); 1209 SE_IBF_SIZE, SE_IBF_HASH_NUM);
1295 return set_state; 1210 return set_state;
@@ -1303,30 +1218,8 @@ union_set_create (void)
1303 * @param element the element to add to the set 1218 * @param element the element to add to the set
1304 */ 1219 */
1305static void 1220static void
1306union_add (struct SetState *set_state, const struct GNUNET_SET_Element *element) 1221union_add (struct SetState *set_state, struct ElementEntry *ee)
1307{ 1222{
1308 struct ElementEntry *ee;
1309 struct ElementEntry *ee_dup;
1310
1311 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "adding union element of size %u\n", element->size);
1312
1313 ee = GNUNET_malloc (element->size + sizeof *ee);
1314 ee->element.size = element->size;
1315 memcpy (&ee[1], element->data, element->size);
1316 ee->element.data = &ee[1];
1317 ee->generation_added = set_state->current_generation;
1318 ee->remote = GNUNET_NO;
1319 GNUNET_CRYPTO_hash (ee->element.data, element->size, &ee->element_hash);
1320 ee_dup = GNUNET_CONTAINER_multihashmap_get (set_state->elements,
1321 &ee->element_hash);
1322 if (NULL != ee_dup)
1323 {
1324 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "element inserted twice, ignoring\n");
1325 GNUNET_free (ee);
1326 return;
1327 }
1328 GNUNET_CONTAINER_multihashmap_put (set_state->elements, &ee->element_hash, ee,
1329 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1330 strata_estimator_insert (set_state->se, get_ibf_key (&ee->element_hash, 0)); 1223 strata_estimator_insert (set_state->se, get_ibf_key (&ee->element_hash, 0));
1331} 1224}
1332 1225
@@ -1348,17 +1241,10 @@ union_set_destroy (struct SetState *set_state)
1348 strata_estimator_destroy (set_state->se); 1241 strata_estimator_destroy (set_state->se);
1349 set_state->se = NULL; 1242 set_state->se = NULL;
1350 } 1243 }
1351 if (NULL != set_state->elements)
1352 {
1353 GNUNET_CONTAINER_multihashmap_iterate (set_state->elements,
1354 destroy_elements_iterator, NULL);
1355 GNUNET_CONTAINER_multihashmap_destroy (set_state->elements);
1356 set_state->elements = NULL;
1357 }
1358
1359 GNUNET_free (set_state); 1244 GNUNET_free (set_state);
1360} 1245}
1361 1246
1247
1362/** 1248/**
1363 * Remove the element given in the element message from the set. 1249 * Remove the element given in the element message from the set.
1364 * Only marks the element as removed, so that older set operations can still exchange it. 1250 * Only marks the element as removed, so that older set operations can still exchange it.
@@ -1367,25 +1253,9 @@ union_set_destroy (struct SetState *set_state)
1367 * @param element set element to remove 1253 * @param element set element to remove
1368 */ 1254 */
1369static void 1255static void
1370union_remove (struct SetState *set_state, const struct GNUNET_SET_Element *element) 1256union_remove (struct SetState *set_state, struct ElementEntry *element)
1371{ 1257{
1372 struct GNUNET_HashCode hash; 1258 /* FIXME: remove from strata estimator */
1373 struct ElementEntry *ee;
1374
1375 GNUNET_CRYPTO_hash (element->data, element->size, &hash);
1376 ee = GNUNET_CONTAINER_multihashmap_get (set_state->elements, &hash);
1377 if (NULL == ee)
1378 {
1379 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "client tried to remove non-existing element\n");
1380 return;
1381 }
1382 if (GNUNET_YES == ee->removed)
1383 {
1384 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "client tried to remove element twice\n");
1385 return;
1386 }
1387 ee->removed = GNUNET_YES;
1388 ee->generation_removed = set_state->current_generation;
1389} 1259}
1390 1260
1391 1261
@@ -1466,55 +1336,6 @@ union_op_cancel (struct SetState *set_state, uint32_t op_id)
1466} 1336}
1467 1337
1468 1338
1469/**
1470 * Iterator over hash map entries.
1471 *
1472 * @param cls closure
1473 * @param key current key code
1474 * @param value value in the hash map
1475 * @return GNUNET_YES if we should continue to
1476 * iterate,
1477 * GNUNET_NO if not.
1478 */
1479static int
1480send_iter_element_iter (void *cls,
1481 const struct GNUNET_HashCode *key,
1482 void *value)
1483{
1484 struct ElementEntry *ee = value;
1485 struct Set *set = cls;
1486 struct GNUNET_SET_IterResponseMessage *m;
1487 struct GNUNET_MQ_Envelope *ev;
1488
1489 ev = GNUNET_MQ_msg_extra (m, ee->element.size,
1490 GNUNET_MESSAGE_TYPE_SET_ITER_ELEMENT);
1491
1492 m->element_type = ee->element.type;
1493 memcpy (&m[1], ee->element.data, ee->element.size);
1494 GNUNET_MQ_send (set->client_mq, ev);
1495
1496 return GNUNET_YES;
1497}
1498
1499
1500/**
1501 * Send all elements of the union set to the client.
1502 *
1503 * @param set set to iterate over
1504 */
1505static void
1506union_iterate (struct Set *set)
1507{
1508 struct GNUNET_MQ_Envelope *ev;
1509
1510 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "iterating union set with %u elements\n",
1511 GNUNET_CONTAINER_multihashmap_size (set->state->elements));
1512 GNUNET_CONTAINER_multihashmap_iterate (set->state->elements, send_iter_element_iter, set);
1513 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_ITER_DONE);
1514 GNUNET_MQ_send (set->client_mq, ev);
1515}
1516
1517
1518const struct SetVT * 1339const struct SetVT *
1519_GSS_union_vt () 1340_GSS_union_vt ()
1520{ 1341{
@@ -1528,7 +1349,6 @@ _GSS_union_vt ()
1528 .accept = &union_accept, 1349 .accept = &union_accept,
1529 .peer_disconnect = &union_peer_disconnect, 1350 .peer_disconnect = &union_peer_disconnect,
1530 .cancel = &union_op_cancel, 1351 .cancel = &union_op_cancel,
1531 .iterate = &union_iterate
1532 }; 1352 };
1533 1353
1534 return &union_vt; 1354 return &union_vt;
diff --git a/src/set/set.h b/src/set/set.h
index ec8390448..8527b6abb 100644
--- a/src/set/set.h
+++ b/src/set/set.h
@@ -227,6 +227,19 @@ struct GNUNET_SET_IterResponseMessage
227 /* rest: element */ 227 /* rest: element */
228}; 228};
229 229
230struct GNUNET_SET_IterAckMessage
231{
232 /**
233 * Type: GNUNET_MESSAGE_TYPE_SET_ITER_ACK
234 */
235 struct GNUNET_MessageHeader header;
236
237 /**
238 * Non-zero if the service should continue sending elements.
239 */
240 uint32_t send_more;
241};
242
230GNUNET_NETWORK_STRUCT_END 243GNUNET_NETWORK_STRUCT_END
231 244
232#endif 245#endif
diff --git a/src/set/set_api.c b/src/set/set_api.c
index 7f52fb0a9..3b287d5a4 100644
--- a/src/set/set_api.c
+++ b/src/set/set_api.c
@@ -222,6 +222,8 @@ handle_iter_element (void *cls, const struct GNUNET_MessageHeader *mh)
222 struct GNUNET_SET_Element element; 222 struct GNUNET_SET_Element element;
223 const struct GNUNET_SET_IterResponseMessage *msg = 223 const struct GNUNET_SET_IterResponseMessage *msg =
224 (const struct GNUNET_SET_IterResponseMessage *) mh; 224 (const struct GNUNET_SET_IterResponseMessage *) mh;
225 struct GNUNET_SET_IterAckMessage *ack_msg;
226 struct GNUNET_MQ_Envelope *ev;
225 227
226 if (NULL == set->iterator) 228 if (NULL == set->iterator)
227 return; 229 return;
@@ -230,6 +232,9 @@ handle_iter_element (void *cls, const struct GNUNET_MessageHeader *mh)
230 element.type = htons (msg->element_type); 232 element.type = htons (msg->element_type);
231 element.data = &msg[1]; 233 element.data = &msg[1];
232 set->iterator (set->iterator_cls, &element); 234 set->iterator (set->iterator_cls, &element);
235 ev = GNUNET_MQ_msg (ack_msg, GNUNET_MESSAGE_TYPE_SET_ITER_ACK);
236 ack_msg->send_more = htonl (1);
237 GNUNET_MQ_send (set->mq, ev);
233} 238}
234 239
235 240
diff --git a/src/set/test_set.conf b/src/set/test_set.conf
index 7bc26ed7e..22df91a40 100644
--- a/src/set/test_set.conf
+++ b/src/set/test_set.conf
@@ -8,7 +8,7 @@ PORT = 2106
8HOSTNAME = localhost 8HOSTNAME = localhost
9HOME = $SERVICEHOME 9HOME = $SERVICEHOME
10BINARY = gnunet-service-set 10BINARY = gnunet-service-set
11#PREFIX = valgrind --leak-check=full 11PREFIX = valgrind
12#PREFIX = gdbserver :1234 12#PREFIX = gdbserver :1234
13ACCEPT_FROM = 127.0.0.1; 13ACCEPT_FROM = 127.0.0.1;
14ACCEPT_FROM6 = ::1; 14ACCEPT_FROM6 = ::1;
diff --git a/src/set/test_set_api.c b/src/set/test_set_api.c
index 59c79ee38..6085c59f3 100644
--- a/src/set/test_set_api.c
+++ b/src/set/test_set_api.c
@@ -36,7 +36,7 @@ static struct GNUNET_SET_Handle *set2;
36static struct GNUNET_SET_ListenHandle *listen_handle; 36static struct GNUNET_SET_ListenHandle *listen_handle;
37const static struct GNUNET_CONFIGURATION_Handle *config; 37const static struct GNUNET_CONFIGURATION_Handle *config;
38 38
39int num_done; 39static int iter_count;
40 40
41 41
42static void 42static void
@@ -144,6 +144,9 @@ init_set2 (void *cls)
144 GNUNET_SET_add_element (set2, &element, NULL, NULL); 144 GNUNET_SET_add_element (set2, &element, NULL, NULL);
145 element.data = "quux"; 145 element.data = "quux";
146 element.size = strlen(element.data); 146 element.size = strlen(element.data);
147 GNUNET_SET_add_element (set2, &element, NULL, NULL);
148 element.data = "baz";
149 element.size = strlen(element.data);
147 GNUNET_SET_add_element (set2, &element, start, NULL); 150 GNUNET_SET_add_element (set2, &element, start, NULL);
148} 151}
149 152
@@ -167,6 +170,44 @@ init_set1 (void)
167} 170}
168 171
169 172
173static int
174iter_cb (void *cls,
175 const struct GNUNET_SET_Element *element)
176{
177 if (NULL == element)
178 {
179 GNUNET_assert (iter_count == 3);
180 GNUNET_SET_destroy (cls);
181 return GNUNET_YES;
182 }
183 printf ("iter: got element\n");
184 iter_count++;
185 return GNUNET_YES;
186}
187
188
189static void
190test_iter ()
191{
192 struct GNUNET_SET_Element element;
193 struct GNUNET_SET_Handle *iter_set;
194
195 iter_set = GNUNET_SET_create (config, GNUNET_SET_OPERATION_UNION);
196
197 element.data = "hello";
198 element.size = strlen(element.data);
199 GNUNET_SET_add_element (iter_set, &element, NULL, NULL);
200 element.data = "bar";
201 element.size = strlen(element.data);
202 GNUNET_SET_add_element (iter_set, &element, NULL, NULL);
203 element.data = "quux";
204 element.size = strlen(element.data);
205 GNUNET_SET_add_element (iter_set, &element, NULL, NULL);
206
207 GNUNET_SET_iterate (iter_set, iter_cb, iter_set);
208}
209
210
170/** 211/**
171 * Signature of the 'main' function for a (single-peer) testcase that 212 * Signature of the 'main' function for a (single-peer) testcase that
172 * is run using 'GNUNET_TESTING_peer_run'. 213 * is run using 'GNUNET_TESTING_peer_run'.
@@ -188,6 +229,10 @@ run (void *cls,
188 printf ("my id (from CRYPTO): %s\n", GNUNET_h2s (&local_id.hashPubKey)); 229 printf ("my id (from CRYPTO): %s\n", GNUNET_h2s (&local_id.hashPubKey));
189 GNUNET_TESTING_peer_get_identity (peer, &local_id); 230 GNUNET_TESTING_peer_get_identity (peer, &local_id);
190 printf ("my id (from TESTING): %s\n", GNUNET_h2s (&local_id.hashPubKey)); 231 printf ("my id (from TESTING): %s\n", GNUNET_h2s (&local_id.hashPubKey));
232
233 test_iter ();
234
235 return;
191 set1 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION); 236 set1 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION);
192 set2 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION); 237 set2 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION);
193 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &app_id); 238 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &app_id);
diff --git a/src/util/container_multihashmap.c b/src/util/container_multihashmap.c
index 9ef8f74a4..a365e81d9 100644
--- a/src/util/container_multihashmap.c
+++ b/src/util/container_multihashmap.c
@@ -872,7 +872,9 @@ GNUNET_CONTAINER_multihashmap_iterator_next (struct GNUNET_CONTAINER_MultiHashMa
872 return GNUNET_YES; 872 return GNUNET_YES;
873 } 873 }
874 } 874 }
875 iter->idx++; 875 iter->idx += 1;
876 if (iter->idx < iter->map->map_length)
877 iter->me = iter->map->map[iter->idx];
876 } 878 }
877} 879}
878 880