diff options
author | Florian Dold <florian.dold@gmail.com> | 2015-08-30 00:44:11 +0000 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2015-08-30 00:44:11 +0000 |
commit | 7936cab9bd741a9ff30362c8495daa29f1874b2e (patch) | |
tree | 33606962451dcb4b15dabff20f605a5c58f1cc72 /src/set/set_api.c | |
parent | 38963d1e81332032e0ac774f4f2c6b804c38802a (diff) | |
download | gnunet-7936cab9bd741a9ff30362c8495daa29f1874b2e.tar.gz gnunet-7936cab9bd741a9ff30362c8495daa29f1874b2e.zip |
work in progress: fix set bug, implement lazy copy
Diffstat (limited to 'src/set/set_api.c')
-rw-r--r-- | src/set/set_api.c | 161 |
1 files changed, 132 insertions, 29 deletions
diff --git a/src/set/set_api.c b/src/set/set_api.c index 04ae019d0..aadc93678 100644 --- a/src/set/set_api.c +++ b/src/set/set_api.c | |||
@@ -33,6 +33,17 @@ | |||
33 | 33 | ||
34 | #define LOG(kind,...) GNUNET_log_from (kind, "set-api",__VA_ARGS__) | 34 | #define LOG(kind,...) GNUNET_log_from (kind, "set-api",__VA_ARGS__) |
35 | 35 | ||
36 | struct SetCopyRequest | ||
37 | { | ||
38 | struct SetCopyRequest *next; | ||
39 | |||
40 | struct SetCopyRequest *prev; | ||
41 | |||
42 | void *cls; | ||
43 | |||
44 | GNUNET_SET_CopyReadyCallback cb; | ||
45 | }; | ||
46 | |||
36 | /** | 47 | /** |
37 | * Opaque handle to a set. | 48 | * Opaque handle to a set. |
38 | */ | 49 | */ |
@@ -84,6 +95,21 @@ struct GNUNET_SET_Handle | |||
84 | * created so far to match replies with iterators. | 95 | * created so far to match replies with iterators. |
85 | */ | 96 | */ |
86 | uint16_t iteration_id; | 97 | uint16_t iteration_id; |
98 | |||
99 | /** | ||
100 | * Configuration, needed when creating (lazy) copies. | ||
101 | */ | ||
102 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
103 | |||
104 | /** | ||
105 | * Doubly linked list of copy requests. | ||
106 | */ | ||
107 | struct SetCopyRequest *copy_req_head; | ||
108 | |||
109 | /** | ||
110 | * Doubly linked list of copy requests. | ||
111 | */ | ||
112 | struct SetCopyRequest *copy_req_tail; | ||
87 | }; | 113 | }; |
88 | 114 | ||
89 | 115 | ||
@@ -213,6 +239,55 @@ struct GNUNET_SET_ListenHandle | |||
213 | }; | 239 | }; |
214 | 240 | ||
215 | 241 | ||
242 | /* mutual recursion with handle_copy_lazy */ | ||
243 | static struct GNUNET_SET_Handle * | ||
244 | create_internal (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
245 | enum GNUNET_SET_OperationType op, | ||
246 | uint32_t *cookie); | ||
247 | |||
248 | |||
249 | /** | ||
250 | * Handle element for iteration over the set. Notifies the | ||
251 | * iterator and sends an acknowledgement to the service. | ||
252 | * | ||
253 | * @param cls the `struct GNUNET_SET_Handle *` | ||
254 | * @param mh the message | ||
255 | */ | ||
256 | static void | ||
257 | handle_copy_lazy (void *cls, | ||
258 | const struct GNUNET_MessageHeader *mh) | ||
259 | { | ||
260 | struct GNUNET_SET_CopyLazyResponseMessage *msg; | ||
261 | struct GNUNET_SET_Handle *set = cls; | ||
262 | struct SetCopyRequest *req; | ||
263 | struct GNUNET_SET_Handle *new_set; | ||
264 | |||
265 | msg = (struct GNUNET_SET_CopyLazyResponseMessage *) mh; | ||
266 | |||
267 | req = set->copy_req_head; | ||
268 | |||
269 | if (NULL == req) | ||
270 | { | ||
271 | /* Service sent us unsolicited lazy copy response */ | ||
272 | GNUNET_break (0); | ||
273 | return; | ||
274 | } | ||
275 | |||
276 | GNUNET_CONTAINER_DLL_remove (set->copy_req_head, | ||
277 | set->copy_req_tail, | ||
278 | req); | ||
279 | |||
280 | |||
281 | // We pass none as operation here, since it doesn't matter when | ||
282 | // cloning. | ||
283 | new_set = create_internal (set->cfg, GNUNET_SET_OPERATION_NONE, &msg->cookie); | ||
284 | |||
285 | req->cb (req->cls, new_set); | ||
286 | |||
287 | GNUNET_free (req); | ||
288 | } | ||
289 | |||
290 | |||
216 | /** | 291 | /** |
217 | * Handle element for iteration over the set. Notifies the | 292 | * Handle element for iteration over the set. Notifies the |
218 | * iterator and sends an acknowledgement to the service. | 293 | * iterator and sends an acknowledgement to the service. |
@@ -455,20 +530,10 @@ handle_client_set_error (void *cls, | |||
455 | } | 530 | } |
456 | 531 | ||
457 | 532 | ||
458 | /** | 533 | static struct GNUNET_SET_Handle * |
459 | * Create an empty set, supporting the specified operation. | 534 | create_internal (const struct GNUNET_CONFIGURATION_Handle *cfg, |
460 | * | 535 | enum GNUNET_SET_OperationType op, |
461 | * @param cfg configuration to use for connecting to the | 536 | uint32_t *cookie) |
462 | * set service | ||
463 | * @param op operation supported by the set | ||
464 | * Note that the operation has to be specified | ||
465 | * beforehand, as certain set operations need to maintain | ||
466 | * data structures spefific to the operation | ||
467 | * @return a handle to the set | ||
468 | */ | ||
469 | struct GNUNET_SET_Handle * | ||
470 | GNUNET_SET_create (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
471 | enum GNUNET_SET_OperationType op) | ||
472 | { | 537 | { |
473 | static const struct GNUNET_MQ_MessageHandler mq_handlers[] = { | 538 | static const struct GNUNET_MQ_MessageHandler mq_handlers[] = { |
474 | { &handle_result, | 539 | { &handle_result, |
@@ -480,17 +545,22 @@ GNUNET_SET_create (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
480 | { &handle_iter_done, | 545 | { &handle_iter_done, |
481 | GNUNET_MESSAGE_TYPE_SET_ITER_DONE, | 546 | GNUNET_MESSAGE_TYPE_SET_ITER_DONE, |
482 | sizeof (struct GNUNET_MessageHeader) }, | 547 | sizeof (struct GNUNET_MessageHeader) }, |
548 | { &handle_copy_lazy, | ||
549 | GNUNET_MESSAGE_TYPE_SET_COPY_LAZY_RESPONSE, | ||
550 | sizeof (struct GNUNET_SET_CopyLazyResponseMessage) }, | ||
483 | GNUNET_MQ_HANDLERS_END | 551 | GNUNET_MQ_HANDLERS_END |
484 | }; | 552 | }; |
485 | struct GNUNET_SET_Handle *set; | 553 | struct GNUNET_SET_Handle *set; |
486 | struct GNUNET_MQ_Envelope *mqm; | 554 | struct GNUNET_MQ_Envelope *mqm; |
487 | struct GNUNET_SET_CreateMessage *msg; | 555 | struct GNUNET_SET_CreateMessage *create_msg; |
556 | struct GNUNET_SET_CopyLazyConnectMessage *copy_msg; | ||
488 | 557 | ||
489 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 558 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
490 | "Creating new set (operation %u)\n", | 559 | "Creating new set (operation %u)\n", |
491 | op); | 560 | op); |
492 | set = GNUNET_new (struct GNUNET_SET_Handle); | 561 | set = GNUNET_new (struct GNUNET_SET_Handle); |
493 | set->client = GNUNET_CLIENT_connect ("set", cfg); | 562 | set->client = GNUNET_CLIENT_connect ("set", cfg); |
563 | set->cfg = cfg; | ||
494 | if (NULL == set->client) | 564 | if (NULL == set->client) |
495 | { | 565 | { |
496 | GNUNET_free (set); | 566 | GNUNET_free (set); |
@@ -501,15 +571,44 @@ GNUNET_SET_create (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
501 | &handle_client_set_error, | 571 | &handle_client_set_error, |
502 | set); | 572 | set); |
503 | GNUNET_assert (NULL != set->mq); | 573 | GNUNET_assert (NULL != set->mq); |
504 | mqm = GNUNET_MQ_msg (msg, | 574 | |
505 | GNUNET_MESSAGE_TYPE_SET_CREATE); | 575 | if (NULL == cookie) |
506 | msg->operation = htonl (op); | 576 | { |
577 | mqm = GNUNET_MQ_msg (create_msg, | ||
578 | GNUNET_MESSAGE_TYPE_SET_CREATE); | ||
579 | create_msg->operation = htonl (op); | ||
580 | } | ||
581 | else | ||
582 | { | ||
583 | mqm = GNUNET_MQ_msg (copy_msg, | ||
584 | GNUNET_MESSAGE_TYPE_SET_COPY_LAZY_CONNECT); | ||
585 | copy_msg->cookie = *cookie; | ||
586 | } | ||
507 | GNUNET_MQ_send (set->mq, mqm); | 587 | GNUNET_MQ_send (set->mq, mqm); |
508 | return set; | 588 | return set; |
509 | } | 589 | } |
510 | 590 | ||
511 | 591 | ||
512 | /** | 592 | /** |
593 | * Create an empty set, supporting the specified operation. | ||
594 | * | ||
595 | * @param cfg configuration to use for connecting to the | ||
596 | * set service | ||
597 | * @param op operation supported by the set | ||
598 | * Note that the operation has to be specified | ||
599 | * beforehand, as certain set operations need to maintain | ||
600 | * data structures spefific to the operation | ||
601 | * @return a handle to the set | ||
602 | */ | ||
603 | struct GNUNET_SET_Handle * | ||
604 | GNUNET_SET_create (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
605 | enum GNUNET_SET_OperationType op) | ||
606 | { | ||
607 | return create_internal (cfg, op, NULL); | ||
608 | } | ||
609 | |||
610 | |||
611 | /** | ||
513 | * Add an element to the given set. After the element has been added | 612 | * Add an element to the given set. After the element has been added |
514 | * (in the sense of being transmitted to the set service), @a cont | 613 | * (in the sense of being transmitted to the set service), @a cont |
515 | * will be called. Multiple calls to GNUNET_SET_add_element() can be | 614 | * will be called. Multiple calls to GNUNET_SET_add_element() can be |
@@ -976,19 +1075,23 @@ GNUNET_SET_iterate (struct GNUNET_SET_Handle *set, | |||
976 | } | 1075 | } |
977 | 1076 | ||
978 | 1077 | ||
979 | /** | ||
980 | * Stop iteration over all elements in the given set. Can only | ||
981 | * be called before the iteration has "naturally" completed its | ||
982 | * turn. | ||
983 | * | ||
984 | * @param set the set to stop iterating over | ||
985 | */ | ||
986 | void | 1078 | void |
987 | GNUNET_SET_iterate_cancel (struct GNUNET_SET_Handle *set) | 1079 | GNUNET_SET_copy_lazy (struct GNUNET_SET_Handle *set, |
1080 | GNUNET_SET_CopyReadyCallback cb, | ||
1081 | void *cls) | ||
988 | { | 1082 | { |
989 | GNUNET_assert (NULL != set->iterator); | 1083 | struct GNUNET_MQ_Envelope *ev; |
990 | set->iterator = NULL; | 1084 | struct SetCopyRequest *req; |
991 | set->iteration_id++; | 1085 | |
1086 | ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_COPY_LAZY_PREPARE); | ||
1087 | GNUNET_MQ_send (set->mq, ev); | ||
1088 | |||
1089 | req = GNUNET_new (struct SetCopyRequest); | ||
1090 | req->cb = cb; | ||
1091 | req->cls = cls; | ||
1092 | GNUNET_CONTAINER_DLL_insert (set->copy_req_head, | ||
1093 | set->copy_req_tail, | ||
1094 | req); | ||
992 | } | 1095 | } |
993 | 1096 | ||
994 | 1097 | ||