diff options
author | Omar Tarabai <tarabai@devegypt.com> | 2014-05-17 16:57:49 +0000 |
---|---|---|
committer | Omar Tarabai <tarabai@devegypt.com> | 2014-05-17 16:57:49 +0000 |
commit | 7eb684ec9f93d52ebae09729fcf01c16580b5cb9 (patch) | |
tree | 72a44f01de2dc157f47a0a70ccb90d36154ddcbf /src/peerstore/peerstore_api.c | |
parent | 83c058a5ea11b6d7aa05cb71963c6063cb373603 (diff) | |
download | gnunet-7eb684ec9f93d52ebae09729fcf01c16580b5cb9.tar.gz gnunet-7eb684ec9f93d52ebae09729fcf01c16580b5cb9.zip |
peestore: towards iterate functionality
Diffstat (limited to 'src/peerstore/peerstore_api.c')
-rw-r--r-- | src/peerstore/peerstore_api.c | 222 |
1 files changed, 217 insertions, 5 deletions
diff --git a/src/peerstore/peerstore_api.c b/src/peerstore/peerstore_api.c index edf506f10..81d6c78a6 100644 --- a/src/peerstore/peerstore_api.c +++ b/src/peerstore/peerstore_api.c | |||
@@ -65,6 +65,16 @@ struct GNUNET_PEERSTORE_Handle | |||
65 | */ | 65 | */ |
66 | struct GNUNET_PEERSTORE_StoreContext *store_tail; | 66 | struct GNUNET_PEERSTORE_StoreContext *store_tail; |
67 | 67 | ||
68 | /** | ||
69 | * Head of active ITERATE requests. | ||
70 | */ | ||
71 | struct GNUNET_PEERSTORE_IterateContext *iterate_head; | ||
72 | |||
73 | /** | ||
74 | * Tail of active ITERATE requests. | ||
75 | */ | ||
76 | struct GNUNET_PEERSTORE_IterateContext *iterate_tail; | ||
77 | |||
68 | }; | 78 | }; |
69 | 79 | ||
70 | /** | 80 | /** |
@@ -110,6 +120,49 @@ struct GNUNET_PEERSTORE_StoreContext | |||
110 | 120 | ||
111 | }; | 121 | }; |
112 | 122 | ||
123 | /** | ||
124 | * Context for a iterate request | ||
125 | */ | ||
126 | struct GNUNET_PEERSTORE_IterateContext | ||
127 | { | ||
128 | /** | ||
129 | * Kept in a DLL. | ||
130 | */ | ||
131 | struct GNUNET_PEERSTORE_IterateContext *next; | ||
132 | |||
133 | /** | ||
134 | * Kept in a DLL. | ||
135 | */ | ||
136 | struct GNUNET_PEERSTORE_IterateContext *prev; | ||
137 | |||
138 | /** | ||
139 | * Handle to the PEERSTORE service. | ||
140 | */ | ||
141 | struct GNUNET_PEERSTORE_Handle *h; | ||
142 | |||
143 | /** | ||
144 | * MQ Envelope with iterate request message | ||
145 | */ | ||
146 | struct GNUNET_MQ_Envelope *ev; | ||
147 | |||
148 | /** | ||
149 | * Callback with each matching record | ||
150 | */ | ||
151 | GNUNET_PEERSTORE_Processor callback; | ||
152 | |||
153 | /** | ||
154 | * Closure for 'callback' | ||
155 | */ | ||
156 | void *callback_cls; | ||
157 | |||
158 | /** | ||
159 | * #GNUNET_YES / #GNUNET_NO | ||
160 | * if sent, cannot be canceled | ||
161 | */ | ||
162 | int request_sent; | ||
163 | |||
164 | }; | ||
165 | |||
113 | /******************************************************************************/ | 166 | /******************************************************************************/ |
114 | /******************* DECLARATIONS *********************/ | 167 | /******************* DECLARATIONS *********************/ |
115 | /******************************************************************************/ | 168 | /******************************************************************************/ |
@@ -122,6 +175,19 @@ struct GNUNET_PEERSTORE_StoreContext | |||
122 | */ | 175 | */ |
123 | void handle_store_result (void *cls, const struct GNUNET_MessageHeader *msg); | 176 | void handle_store_result (void *cls, const struct GNUNET_MessageHeader *msg); |
124 | 177 | ||
178 | /** | ||
179 | * When a response for iterate request is received | ||
180 | * | ||
181 | * @param cls a 'struct GNUNET_PEERSTORE_Handle *' | ||
182 | * @param msg message received, NULL on timeout or fatal error | ||
183 | */ | ||
184 | void handle_iterate_result (void *cls, const struct GNUNET_MessageHeader *msg); | ||
185 | |||
186 | /** | ||
187 | * Close the existing connection to PEERSTORE and reconnect. | ||
188 | * | ||
189 | * @param h handle to the service | ||
190 | */ | ||
125 | static void | 191 | static void |
126 | reconnect (struct GNUNET_PEERSTORE_Handle *h); | 192 | reconnect (struct GNUNET_PEERSTORE_Handle *h); |
127 | 193 | ||
@@ -131,6 +197,8 @@ reconnect (struct GNUNET_PEERSTORE_Handle *h); | |||
131 | static const struct GNUNET_MQ_MessageHandler mq_handlers[] = { | 197 | static const struct GNUNET_MQ_MessageHandler mq_handlers[] = { |
132 | {&handle_store_result, GNUNET_MESSAGE_TYPE_PEERSTORE_STORE_RESULT_OK, sizeof(struct GNUNET_MessageHeader)}, | 198 | {&handle_store_result, GNUNET_MESSAGE_TYPE_PEERSTORE_STORE_RESULT_OK, sizeof(struct GNUNET_MessageHeader)}, |
133 | {&handle_store_result, GNUNET_MESSAGE_TYPE_PEERSTORE_STORE_RESULT_FAIL, sizeof(struct GNUNET_MessageHeader)}, | 199 | {&handle_store_result, GNUNET_MESSAGE_TYPE_PEERSTORE_STORE_RESULT_FAIL, sizeof(struct GNUNET_MessageHeader)}, |
200 | {&handle_iterate_result, GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_RECORD, 0}, | ||
201 | {&handle_iterate_result, GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_END, sizeof(struct GNUNET_MessageHeader)}, | ||
134 | GNUNET_MQ_HANDLERS_END | 202 | GNUNET_MQ_HANDLERS_END |
135 | }; | 203 | }; |
136 | 204 | ||
@@ -154,12 +222,18 @@ static void | |||
154 | cleanup_handle(struct GNUNET_PEERSTORE_Handle *h) | 222 | cleanup_handle(struct GNUNET_PEERSTORE_Handle *h) |
155 | { | 223 | { |
156 | struct GNUNET_PEERSTORE_StoreContext *sc; | 224 | struct GNUNET_PEERSTORE_StoreContext *sc; |
225 | struct GNUNET_PEERSTORE_IterateContext *ic; | ||
157 | 226 | ||
158 | while (NULL != (sc = h->store_head)) | 227 | while (NULL != (sc = h->store_head)) |
159 | { | 228 | { |
160 | GNUNET_CONTAINER_DLL_remove(h->store_head, h->store_tail, sc); | 229 | GNUNET_CONTAINER_DLL_remove(h->store_head, h->store_tail, sc); |
161 | GNUNET_free(sc); | 230 | GNUNET_free(sc); |
162 | } | 231 | } |
232 | while (NULL != (ic = h->iterate_head)) | ||
233 | { | ||
234 | GNUNET_CONTAINER_DLL_remove(h->iterate_head, h->iterate_tail, ic); | ||
235 | GNUNET_free(ic); | ||
236 | } | ||
163 | } | 237 | } |
164 | 238 | ||
165 | /** | 239 | /** |
@@ -254,7 +328,7 @@ GNUNET_PEERSTORE_disconnect(struct GNUNET_PEERSTORE_Handle *h) | |||
254 | /** | 328 | /** |
255 | * When a response for store request is received | 329 | * When a response for store request is received |
256 | * | 330 | * |
257 | * @param cls a 'struct GNUNET_PEERSTORE_StoreContext *' | 331 | * @param cls a 'struct GNUNET_PEERSTORE_Handle *' |
258 | * @param msg message received, NULL on timeout or fatal error | 332 | * @param msg message received, NULL on timeout or fatal error |
259 | */ | 333 | */ |
260 | void handle_store_result (void *cls, const struct GNUNET_MessageHeader *msg) | 334 | void handle_store_result (void *cls, const struct GNUNET_MessageHeader *msg) |
@@ -304,6 +378,7 @@ void store_request_sent (void *cls) | |||
304 | struct GNUNET_PEERSTORE_StoreContext *sc = cls; | 378 | struct GNUNET_PEERSTORE_StoreContext *sc = cls; |
305 | 379 | ||
306 | sc->request_sent = GNUNET_YES; | 380 | sc->request_sent = GNUNET_YES; |
381 | sc->ev = NULL; | ||
307 | } | 382 | } |
308 | 383 | ||
309 | /** | 384 | /** |
@@ -319,7 +394,10 @@ GNUNET_PEERSTORE_store_cancel (struct GNUNET_PEERSTORE_StoreContext *sc) | |||
319 | if(GNUNET_NO == sc->request_sent) | 394 | if(GNUNET_NO == sc->request_sent) |
320 | { | 395 | { |
321 | if(NULL != sc->ev) | 396 | if(NULL != sc->ev) |
322 | GNUNET_MQ_discard(sc->ev); | 397 | { |
398 | //GNUNET_MQ_discard(sc->ev); //FIXME: this should be GNUNET_MQ_send_cancel | ||
399 | sc->ev = NULL; | ||
400 | } | ||
323 | GNUNET_CONTAINER_DLL_remove(sc->h->store_head, sc->h->store_tail, sc); | 401 | GNUNET_CONTAINER_DLL_remove(sc->h->store_head, sc->h->store_tail, sc); |
324 | GNUNET_free(sc); | 402 | GNUNET_free(sc); |
325 | } | 403 | } |
@@ -365,10 +443,8 @@ GNUNET_PEERSTORE_store (struct GNUNET_PEERSTORE_Handle *h, | |||
365 | key, | 443 | key, |
366 | value, | 444 | value, |
367 | size, | 445 | size, |
368 | expiry, | 446 | &expiry, |
369 | GNUNET_MESSAGE_TYPE_PEERSTORE_STORE); | 447 | GNUNET_MESSAGE_TYPE_PEERSTORE_STORE); |
370 | GNUNET_MQ_send(h->mq, ev); | ||
371 | GNUNET_MQ_notify_sent(ev, &store_request_sent, ev); | ||
372 | sc = GNUNET_new(struct GNUNET_PEERSTORE_StoreContext); | 448 | sc = GNUNET_new(struct GNUNET_PEERSTORE_StoreContext); |
373 | sc->ev = ev; | 449 | sc->ev = ev; |
374 | sc->cont = cont; | 450 | sc->cont = cont; |
@@ -376,8 +452,144 @@ GNUNET_PEERSTORE_store (struct GNUNET_PEERSTORE_Handle *h, | |||
376 | sc->h = h; | 452 | sc->h = h; |
377 | sc->request_sent = GNUNET_NO; | 453 | sc->request_sent = GNUNET_NO; |
378 | GNUNET_CONTAINER_DLL_insert(h->store_head, h->store_tail, sc); | 454 | GNUNET_CONTAINER_DLL_insert(h->store_head, h->store_tail, sc); |
455 | GNUNET_MQ_notify_sent(ev, &store_request_sent, ev); | ||
456 | GNUNET_MQ_send(h->mq, ev); | ||
379 | return sc; | 457 | return sc; |
380 | 458 | ||
381 | } | 459 | } |
382 | 460 | ||
461 | /******************************************************************************/ | ||
462 | /******************* ITERATE FUNCTIONS *********************/ | ||
463 | /******************************************************************************/ | ||
464 | |||
465 | /** | ||
466 | * When a response for iterate request is received | ||
467 | * | ||
468 | * @param cls a 'struct GNUNET_PEERSTORE_Handle *' | ||
469 | * @param msg message received, NULL on timeout or fatal error | ||
470 | */ | ||
471 | void handle_iterate_result (void *cls, const struct GNUNET_MessageHeader *msg) | ||
472 | { | ||
473 | struct GNUNET_PEERSTORE_Handle *h = cls; | ||
474 | struct GNUNET_PEERSTORE_IterateContext *ic; | ||
475 | GNUNET_PEERSTORE_Processor callback; | ||
476 | void *callback_cls; | ||
477 | uint16_t msg_type; | ||
478 | struct GNUNET_PEERSTORE_Record *record; | ||
479 | |||
480 | ic = h->iterate_head; | ||
481 | if(NULL == ic) | ||
482 | { | ||
483 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Unexpected iteration response, this should not happen.\n"); | ||
484 | reconnect(h); | ||
485 | return; | ||
486 | } | ||
487 | callback = ic->callback; | ||
488 | callback_cls = ic->callback_cls; | ||
489 | if(NULL == msg) /* Connection error */ | ||
490 | { | ||
491 | |||
492 | if(NULL != callback) | ||
493 | callback(callback_cls, NULL, | ||
494 | _("Error communicating with `PEERSTORE' service.")); | ||
495 | reconnect(h); | ||
496 | return; | ||
497 | } | ||
498 | msg_type = ntohs(msg->type); | ||
499 | if(GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_END == msg_type) | ||
500 | { | ||
501 | if(NULL != callback) | ||
502 | callback(callback_cls, NULL, NULL); | ||
503 | GNUNET_CONTAINER_DLL_remove(ic->h->iterate_head, ic->h->iterate_tail, ic); | ||
504 | GNUNET_free(ic); | ||
505 | return; | ||
506 | } | ||
507 | if(NULL != callback) | ||
508 | { | ||
509 | record = PEERSTORE_parse_record_message(msg); | ||
510 | if(NULL == record) | ||
511 | callback(callback_cls, record, _("Received a malformed response from service.")); | ||
512 | else | ||
513 | callback(callback_cls, record, NULL); | ||
514 | } | ||
515 | |||
516 | } | ||
517 | |||
518 | /** | ||
519 | * Callback after MQ envelope is sent | ||
520 | * | ||
521 | * @param cls a 'struct GNUNET_PEERSTORE_IterateContext *' | ||
522 | */ | ||
523 | void iterate_request_sent (void *cls) | ||
524 | { | ||
525 | struct GNUNET_PEERSTORE_IterateContext *ic = cls; | ||
526 | |||
527 | ic->request_sent = GNUNET_YES; | ||
528 | ic->ev = NULL; | ||
529 | } | ||
530 | |||
531 | /** | ||
532 | * Cancel an iterate request | ||
533 | * Please do not call after the iterate request is done | ||
534 | * | ||
535 | * @param ic Iterate request context as returned by GNUNET_PEERSTORE_iterate() | ||
536 | */ | ||
537 | void | ||
538 | GNUNET_PEERSTORE_iterate_cancel (struct GNUNET_PEERSTORE_IterateContext *ic) | ||
539 | { | ||
540 | if(GNUNET_NO == ic->request_sent) | ||
541 | { | ||
542 | if(NULL != ic->ev) | ||
543 | { | ||
544 | //GNUNET_MQ_discard(ic->ev); //FIXME: this should be GNUNET_MQ_send_cancel | ||
545 | ic->ev = NULL; | ||
546 | } | ||
547 | GNUNET_CONTAINER_DLL_remove(ic->h->iterate_head, ic->h->iterate_tail, ic); | ||
548 | GNUNET_free(ic); | ||
549 | } | ||
550 | else | ||
551 | ic->callback = NULL; | ||
552 | } | ||
553 | |||
554 | /** | ||
555 | * Iterate over records matching supplied key information | ||
556 | * | ||
557 | * @param h handle to the PEERSTORE service | ||
558 | * @param sub_system name of sub system | ||
559 | * @param peer Peer identity (can be NULL) | ||
560 | * @param key entry key string (can be NULL) | ||
561 | * @param timeout time after which the iterate request is canceled | ||
562 | * @param callback function called with each matching record, all NULL's on end | ||
563 | * @param callback_cls closure for @a callback | ||
564 | */ | ||
565 | struct GNUNET_PEERSTORE_IterateContext * | ||
566 | GNUNET_PEERSTORE_iterate (struct GNUNET_PEERSTORE_Handle *h, | ||
567 | char *sub_system, | ||
568 | const struct GNUNET_PeerIdentity *peer, | ||
569 | const char *key, | ||
570 | struct GNUNET_TIME_Relative timeout, //FIXME: handle timeout | ||
571 | GNUNET_PEERSTORE_Processor callback, void *callback_cls) | ||
572 | { | ||
573 | struct GNUNET_MQ_Envelope *ev; | ||
574 | struct GNUNET_PEERSTORE_IterateContext *ic; | ||
575 | |||
576 | ev = PEERSTORE_create_record_mq_envelope(sub_system, | ||
577 | peer, | ||
578 | key, | ||
579 | NULL, | ||
580 | 0, | ||
581 | NULL, | ||
582 | GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE); | ||
583 | ic = GNUNET_new(struct GNUNET_PEERSTORE_IterateContext); | ||
584 | ic->callback = callback; | ||
585 | ic->callback_cls = callback_cls; | ||
586 | ic->ev = ev; | ||
587 | ic->h = h; | ||
588 | ic->request_sent = GNUNET_NO; | ||
589 | GNUNET_CONTAINER_DLL_insert(h->iterate_head, h->iterate_tail, ic); | ||
590 | GNUNET_MQ_notify_sent(ev, &iterate_request_sent, ev); | ||
591 | GNUNET_MQ_send(h->mq, ev); | ||
592 | return ic; | ||
593 | } | ||
594 | |||
383 | /* end of peerstore_api.c */ | 595 | /* end of peerstore_api.c */ |