diff options
author | Sree Harsha Totakura <totakura@in.tum.de> | 2013-01-30 15:06:52 +0000 |
---|---|---|
committer | Sree Harsha Totakura <totakura@in.tum.de> | 2013-01-30 15:06:52 +0000 |
commit | ff3529ccfc3f7df86531900b40dd37dc0617387b (patch) | |
tree | f3cbb4df96ae66cc194a4bb92e88362eb55006c0 /src | |
parent | f3b225f570302afef710c58e22b75efd81e71e56 (diff) | |
download | gnunet-ff3529ccfc3f7df86531900b40dd37dc0617387b.tar.gz gnunet-ff3529ccfc3f7df86531900b40dd37dc0617387b.zip |
towards caching CORE handles
Diffstat (limited to 'src')
-rw-r--r-- | src/testbed/gnunet-service-testbed_hc.c | 285 |
1 files changed, 245 insertions, 40 deletions
diff --git a/src/testbed/gnunet-service-testbed_hc.c b/src/testbed/gnunet-service-testbed_hc.c index ecc2e5edc..7810d32ac 100644 --- a/src/testbed/gnunet-service-testbed_hc.c +++ b/src/testbed/gnunet-service-testbed_hc.c | |||
@@ -36,6 +36,26 @@ | |||
36 | GNUNET_log_from (kind, "testbed-cache", __VA_ARGS__) | 36 | GNUNET_log_from (kind, "testbed-cache", __VA_ARGS__) |
37 | 37 | ||
38 | 38 | ||
39 | /** | ||
40 | * Type of cache-get requests | ||
41 | */ | ||
42 | enum CacheGetType | ||
43 | { | ||
44 | /** | ||
45 | * Get transport handle | ||
46 | */ | ||
47 | CGT_TRANSPORT_HANDLE = 1, | ||
48 | |||
49 | /** | ||
50 | * Get core handle | ||
51 | */ | ||
52 | CGT_CORE_HANDLE | ||
53 | }; | ||
54 | |||
55 | |||
56 | /** | ||
57 | * The cache-get request handle | ||
58 | */ | ||
39 | struct GSTCacheGetHandle; | 59 | struct GSTCacheGetHandle; |
40 | 60 | ||
41 | 61 | ||
@@ -78,28 +98,49 @@ struct ConnectNotifyContext | |||
78 | }; | 98 | }; |
79 | 99 | ||
80 | 100 | ||
81 | enum CacheGetType | 101 | /** |
82 | { | 102 | * The cache-get request handle |
83 | CGT_TRANSPORT_HANDLE = 1 | 103 | */ |
84 | }; | ||
85 | |||
86 | |||
87 | struct GSTCacheGetHandle | 104 | struct GSTCacheGetHandle |
88 | { | 105 | { |
106 | /** | ||
107 | * The next ptr for the DLL. Used in struct CacheEntry | ||
108 | */ | ||
89 | struct GSTCacheGetHandle *next; | 109 | struct GSTCacheGetHandle *next; |
90 | 110 | ||
111 | /** | ||
112 | * The prev ptr for the DLL. Used in struct CacheEntry | ||
113 | */ | ||
91 | struct GSTCacheGetHandle *prev; | 114 | struct GSTCacheGetHandle *prev; |
92 | 115 | ||
116 | /** | ||
117 | * The cache entry object this handle corresponds to | ||
118 | */ | ||
93 | struct CacheEntry *entry; | 119 | struct CacheEntry *entry; |
94 | 120 | ||
121 | /** | ||
122 | * The cache callback to call when a handle is available | ||
123 | */ | ||
95 | GST_cache_callback cb; | 124 | GST_cache_callback cb; |
96 | 125 | ||
126 | /** | ||
127 | * The closure for the above callback | ||
128 | */ | ||
97 | void *cb_cls; | 129 | void *cb_cls; |
98 | 130 | ||
131 | /** | ||
132 | * The peer connect notify context created for this handle; can be NULL | ||
133 | */ | ||
99 | struct ConnectNotifyContext *nctxt; | 134 | struct ConnectNotifyContext *nctxt; |
100 | 135 | ||
136 | /** | ||
137 | * The type of this cache-get request | ||
138 | */ | ||
101 | enum CacheGetType type; | 139 | enum CacheGetType type; |
102 | 140 | ||
141 | /** | ||
142 | * Did we call the cache callback already? | ||
143 | */ | ||
103 | int notify_called; | 144 | int notify_called; |
104 | }; | 145 | }; |
105 | 146 | ||
@@ -121,12 +162,22 @@ struct CacheEntry | |||
121 | /** | 162 | /** |
122 | * The transport handle to the peer corresponding to this entry; can be NULL | 163 | * The transport handle to the peer corresponding to this entry; can be NULL |
123 | */ | 164 | */ |
124 | struct GNUNET_TRANSPORT_Handle *transport_handle; | 165 | struct GNUNET_TRANSPORT_Handle *transport_handle_; |
125 | 166 | ||
126 | /** | 167 | /** |
127 | * The operation handle for transport handle | 168 | * The operation handle for transport handle |
128 | */ | 169 | */ |
129 | struct GNUNET_TESTBED_Operation *transport_op; | 170 | struct GNUNET_TESTBED_Operation *transport_op_; |
171 | |||
172 | /** | ||
173 | * The core handle to the peer corresponding to this entry; can be NULL | ||
174 | */ | ||
175 | struct GNUNET_CORE_Handle *core_handle; | ||
176 | |||
177 | /** | ||
178 | * The operation handle for core handle | ||
179 | */ | ||
180 | struct GNUNET_TESTBED_Operation *core_op; | ||
130 | 181 | ||
131 | /** | 182 | /** |
132 | * The configuration of the peer. Should be not NULL as long as the core_handle | 183 | * The configuration of the peer. Should be not NULL as long as the core_handle |
@@ -239,16 +290,19 @@ cache_lookup (const struct GNUNET_HashCode *key) | |||
239 | 290 | ||
240 | static struct CacheEntry * | 291 | static struct CacheEntry * |
241 | cache_lookup_handles (const struct GNUNET_HashCode *pid, | 292 | cache_lookup_handles (const struct GNUNET_HashCode *pid, |
242 | struct GNUNET_TRANSPORT_Handle **th) | 293 | struct GNUNET_TRANSPORT_Handle **th, |
294 | struct GNUNET_CORE_Handle **ch) | ||
243 | { | 295 | { |
244 | struct CacheEntry *entry; | 296 | struct CacheEntry *entry; |
245 | 297 | ||
246 | GNUNET_assert (NULL != th); | 298 | GNUNET_assert ((NULL != th) || (NULL != ch)); |
247 | entry = cache_lookup (pid); | 299 | entry = cache_lookup (pid); |
248 | if (NULL == entry) | 300 | if (NULL == entry) |
249 | return NULL; | 301 | return NULL; |
250 | if (NULL != entry->transport_handle) | 302 | if ((NULL != entry->transport_handle_) && (NULL != th)) |
251 | *th = entry->transport_handle; | 303 | *th = entry->transport_handle_; |
304 | if ((NULL != entry->core_handle) && (NULL != ch)) | ||
305 | *ch = entry->core_handle; | ||
252 | return entry; | 306 | return entry; |
253 | } | 307 | } |
254 | 308 | ||
@@ -256,17 +310,30 @@ cache_lookup_handles (const struct GNUNET_HashCode *pid, | |||
256 | static void | 310 | static void |
257 | cache_remove (struct CacheEntry *entry) | 311 | cache_remove (struct CacheEntry *entry) |
258 | { | 312 | { |
313 | struct ConnectNotifyContext *ctxt; | ||
314 | |||
259 | /* We keep the entry in the hash table so that the HELLO can still be found | 315 | /* We keep the entry in the hash table so that the HELLO can still be found |
260 | in cache; we will however disconnect the core and transport handles */ | 316 | in cache; we will however disconnect the core and transport handles */ |
261 | GNUNET_assert (0 == entry->demand); | 317 | GNUNET_assert (0 == entry->demand); |
262 | if ((NULL != entry->next) || (NULL != entry->prev)) | 318 | if ((NULL != entry->next) || (NULL != entry->prev)) |
263 | GNUNET_CONTAINER_DLL_remove (lru_cache_head, lru_cache_tail, entry); | 319 | GNUNET_CONTAINER_DLL_remove (lru_cache_head, lru_cache_tail, entry); |
320 | while (NULL != (ctxt = entry->nctxt_qhead)) | ||
321 | { | ||
322 | GNUNET_CONTAINER_DLL_remove (entry->nctxt_qhead, entry->nctxt_qtail, ctxt); | ||
323 | GNUNET_free (ctxt); | ||
324 | } | ||
264 | LOG_DEBUG ("Cleaning up handles from an entry in cache\n"); | 325 | LOG_DEBUG ("Cleaning up handles from an entry in cache\n"); |
265 | if (NULL != entry->transport_handle) | 326 | if (NULL != entry->transport_handle_) |
327 | { | ||
328 | GNUNET_assert (NULL != entry->transport_op_); | ||
329 | GNUNET_TESTBED_operation_done (entry->transport_op_); | ||
330 | entry->transport_op_ = NULL; | ||
331 | } | ||
332 | if (NULL != entry->core_handle) | ||
266 | { | 333 | { |
267 | GNUNET_assert (NULL != entry->transport_op); | 334 | GNUNET_assert (NULL != entry->core_op); |
268 | GNUNET_TESTBED_operation_done (entry->transport_op); | 335 | GNUNET_TESTBED_operation_done (entry->core_op); |
269 | entry->transport_op = NULL; | 336 | entry->core_op = NULL; |
270 | } | 337 | } |
271 | if (NULL != entry->cfg) | 338 | if (NULL != entry->cfg) |
272 | { | 339 | { |
@@ -311,7 +378,10 @@ call_cgh_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
311 | switch (cgh->type) | 378 | switch (cgh->type) |
312 | { | 379 | { |
313 | case CGT_TRANSPORT_HANDLE: | 380 | case CGT_TRANSPORT_HANDLE: |
314 | cgh->cb (cgh->cb_cls, NULL, entry->transport_handle); | 381 | cgh->cb (cgh->cb_cls, NULL, entry->transport_handle_); |
382 | break; | ||
383 | case CGT_CORE_HANDLE: | ||
384 | cgh->cb (cgh->cb_cls, entry->core_handle, NULL); | ||
315 | break; | 385 | break; |
316 | } | 386 | } |
317 | } | 387 | } |
@@ -361,17 +431,17 @@ opstart_get_handle_transport (void *cls) | |||
361 | 431 | ||
362 | GNUNET_assert (NULL != entry); | 432 | GNUNET_assert (NULL != entry); |
363 | LOG_DEBUG ("Opening a transport connection to peer %u\n", entry->peer_id); | 433 | LOG_DEBUG ("Opening a transport connection to peer %u\n", entry->peer_id); |
364 | entry->transport_handle = GNUNET_TRANSPORT_connect (entry->cfg, | 434 | entry->transport_handle_ = GNUNET_TRANSPORT_connect (entry->cfg, |
365 | NULL, entry, | 435 | NULL, entry, |
366 | NULL, | 436 | NULL, |
367 | &peer_connect_notify_cb, | 437 | &peer_connect_notify_cb, |
368 | NULL); | 438 | NULL); |
369 | if (NULL == entry->transport_handle) | 439 | if (NULL == entry->transport_handle_) |
370 | { | 440 | { |
371 | GNUNET_break (0); | 441 | GNUNET_break (0); |
372 | return; | 442 | return; |
373 | } | 443 | } |
374 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == entry->notify_task); | 444 | //GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == entry->notify_task); |
375 | if (0 == entry->demand) | 445 | if (0 == entry->demand) |
376 | return; | 446 | return; |
377 | if (GNUNET_NO == entry->cgh_qhead->notify_called) | 447 | if (GNUNET_NO == entry->cgh_qhead->notify_called) |
@@ -383,17 +453,97 @@ static void | |||
383 | oprelease_get_handle_transport (void *cls) | 453 | oprelease_get_handle_transport (void *cls) |
384 | { | 454 | { |
385 | struct CacheEntry *entry = cls; | 455 | struct CacheEntry *entry = cls; |
386 | struct ConnectNotifyContext *ctxt; | ||
387 | 456 | ||
388 | while (NULL != (ctxt = entry->nctxt_qhead)) | 457 | if (NULL == entry->transport_handle_) |
458 | return; | ||
459 | GNUNET_TRANSPORT_disconnect (entry->transport_handle_); | ||
460 | entry->transport_handle_ = NULL; | ||
461 | } | ||
462 | |||
463 | |||
464 | /** | ||
465 | * Function called after GNUNET_CORE_connect has succeeded (or failed | ||
466 | * for good). Note that the private key of the peer is intentionally | ||
467 | * not exposed here; if you need it, your process should try to read | ||
468 | * the private key file directly (which should work if you are | ||
469 | * authorized...). Implementations of this function must not call | ||
470 | * GNUNET_CORE_disconnect (other than by scheduling a new task to | ||
471 | * do this later). | ||
472 | * | ||
473 | * @param cls closure | ||
474 | * @param server handle to the server, NULL if we failed | ||
475 | * @param my_identity ID of this peer, NULL if we failed | ||
476 | */ | ||
477 | static void core_startup_cb (void *cls, | ||
478 | struct GNUNET_CORE_Handle * server, | ||
479 | const struct GNUNET_PeerIdentity * | ||
480 | my_identity) | ||
481 | { | ||
482 | GNUNET_break (0); | ||
483 | } | ||
484 | |||
485 | |||
486 | /** | ||
487 | * Method called whenever a given peer connects. | ||
488 | * | ||
489 | * @param cls closure | ||
490 | * @param peer peer identity this notification is about | ||
491 | * @param atsi performance data for the connection | ||
492 | * @param atsi_count number of records in 'atsi' | ||
493 | */ | ||
494 | static void | ||
495 | core_peer_connect_cb (void *cls, | ||
496 | const struct GNUNET_PeerIdentity * peer, | ||
497 | const struct GNUNET_ATS_Information * atsi, | ||
498 | unsigned int atsi_count) | ||
499 | { | ||
500 | struct CacheEntry *entry = cls; | ||
501 | |||
502 | if (0 == entry->demand) | ||
503 | return; | ||
504 | if (GNUNET_NO == entry->cgh_qhead->notify_called) | ||
505 | entry->notify_task = GNUNET_SCHEDULER_add_now (&call_cgh_cb, entry); | ||
506 | } | ||
507 | |||
508 | |||
509 | static void | ||
510 | opstart_get_handle_core (void *cls) | ||
511 | { | ||
512 | struct CacheEntry *entry = cls; | ||
513 | const struct GNUNET_CORE_MessageHandler no_handlers[] = { | ||
514 | {NULL, 0, 0} | ||
515 | }; | ||
516 | |||
517 | GNUNET_assert (NULL != entry); | ||
518 | LOG_DEBUG ("Opening a CORE connection to peer %u\n", entry->peer_id); | ||
519 | entry->core_handle = GNUNET_CORE_connect (entry->cfg, | ||
520 | entry, | ||
521 | &core_startup_cb, | ||
522 | &core_peer_connect_cb, | ||
523 | NULL, /* disconnect cb */ | ||
524 | NULL, /* inbound notify */ | ||
525 | GNUNET_NO, | ||
526 | NULL, /* outbound notify */ | ||
527 | GNUNET_NO, | ||
528 | no_handlers); | ||
529 | if (NULL == entry->core_handle) | ||
389 | { | 530 | { |
390 | GNUNET_CONTAINER_DLL_remove (entry->nctxt_qhead, entry->nctxt_qtail, ctxt); | 531 | GNUNET_break (0); |
391 | GNUNET_free (ctxt); | 532 | return; |
392 | } | 533 | } |
393 | if (NULL == entry->transport_handle) | 534 | //GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == entry->notify_task); |
535 | } | ||
536 | |||
537 | |||
538 | static void | ||
539 | oprelease_get_handle_core (void *cls) | ||
540 | { | ||
541 | struct CacheEntry *entry = cls; | ||
542 | |||
543 | if (NULL == entry->core_handle) | ||
394 | return; | 544 | return; |
395 | GNUNET_TRANSPORT_disconnect (entry->transport_handle); | 545 | GNUNET_CORE_disconnect (entry->core_handle); |
396 | entry->transport_handle = NULL; | 546 | entry->core_handle = NULL; |
397 | } | 547 | } |
398 | 548 | ||
399 | 549 | ||
@@ -409,6 +559,7 @@ cache_get_handle (unsigned int peer_id, | |||
409 | void *handle; | 559 | void *handle; |
410 | struct CacheEntry *entry; | 560 | struct CacheEntry *entry; |
411 | struct ConnectNotifyContext *ctxt; | 561 | struct ConnectNotifyContext *ctxt; |
562 | struct GNUNET_TESTBED_Operation *op; | ||
412 | 563 | ||
413 | GNUNET_assert (0 != cgh->type); | 564 | GNUNET_assert (0 != cgh->type); |
414 | GNUNET_CRYPTO_hash (&peer_id, sizeof (peer_id), &key); | 565 | GNUNET_CRYPTO_hash (&peer_id, sizeof (peer_id), &key); |
@@ -417,7 +568,12 @@ cache_get_handle (unsigned int peer_id, | |||
417 | switch (cgh->type) | 568 | switch (cgh->type) |
418 | { | 569 | { |
419 | case CGT_TRANSPORT_HANDLE: | 570 | case CGT_TRANSPORT_HANDLE: |
420 | entry = cache_lookup_handles (&key, (struct GNUNET_TRANSPORT_Handle **) &handle); | 571 | entry = cache_lookup_handles (&key, (struct GNUNET_TRANSPORT_Handle **) |
572 | &handle, NULL); | ||
573 | break; | ||
574 | case CGT_CORE_HANDLE: | ||
575 | entry = cache_lookup_handles (&key, NULL, | ||
576 | (struct GNUNET_CORE_Handle **) &handle); | ||
421 | break; | 577 | break; |
422 | } | 578 | } |
423 | if (NULL != handle) | 579 | if (NULL != handle) |
@@ -445,25 +601,31 @@ cache_get_handle (unsigned int peer_id, | |||
445 | ctxt->cgh = cgh; | 601 | ctxt->cgh = cgh; |
446 | GNUNET_CONTAINER_DLL_insert_tail (entry->nctxt_qhead, entry->nctxt_qtail, ctxt); | 602 | GNUNET_CONTAINER_DLL_insert_tail (entry->nctxt_qhead, entry->nctxt_qtail, ctxt); |
447 | } | 603 | } |
448 | if ((NULL != entry->transport_handle) | 604 | if (NULL != handle) |
449 | && (GNUNET_SCHEDULER_NO_TASK == entry->notify_task)) | ||
450 | { | 605 | { |
451 | entry->notify_task = GNUNET_SCHEDULER_add_now (&call_cgh_cb, entry); | 606 | if (GNUNET_SCHEDULER_NO_TASK == entry->notify_task) |
607 | entry->notify_task = GNUNET_SCHEDULER_add_now (&call_cgh_cb, entry); | ||
452 | return cgh; | 608 | return cgh; |
453 | } | 609 | } |
454 | if (NULL != entry->transport_op) | ||
455 | return cgh; | ||
456 | switch (cgh->type) | 610 | switch (cgh->type) |
457 | { | 611 | { |
458 | case CGT_TRANSPORT_HANDLE: | 612 | case CGT_TRANSPORT_HANDLE: |
459 | GNUNET_assert (NULL == entry->transport_op); | 613 | if (NULL != entry->transport_op_) |
460 | entry->transport_op = GNUNET_TESTBED_operation_create_ (entry, &opstart_get_handle_transport, | 614 | return cgh; |
461 | &oprelease_get_handle_transport); | 615 | op = GNUNET_TESTBED_operation_create_ (entry, &opstart_get_handle_transport, |
462 | GNUNET_TESTBED_operation_queue_insert_ (GST_opq_openfds, | 616 | &oprelease_get_handle_transport); |
463 | entry->transport_op); | 617 | entry->transport_op_ = op; |
464 | GNUNET_TESTBED_operation_begin_wait_ (entry->transport_op); | 618 | break; |
619 | case CGT_CORE_HANDLE: | ||
620 | if (NULL != entry->core_op) | ||
621 | return cgh; | ||
622 | op = GNUNET_TESTBED_operation_create_ (entry, &opstart_get_handle_core, | ||
623 | &oprelease_get_handle_core); | ||
624 | entry->core_op = op; | ||
465 | break; | 625 | break; |
466 | } | 626 | } |
627 | GNUNET_TESTBED_operation_queue_insert_ (GST_opq_openfds, op); | ||
628 | GNUNET_TESTBED_operation_begin_wait_ (op); | ||
467 | return cgh; | 629 | return cgh; |
468 | } | 630 | } |
469 | 631 | ||
@@ -492,7 +654,10 @@ cache_clear_iterator (void *cls, | |||
492 | if (0 == entry->demand) | 654 | if (0 == entry->demand) |
493 | cache_remove (entry); | 655 | cache_remove (entry); |
494 | GNUNET_free_non_null (entry->hello); | 656 | GNUNET_free_non_null (entry->hello); |
495 | GNUNET_break (NULL == entry->transport_handle); | 657 | GNUNET_break (NULL == entry->transport_handle_); |
658 | GNUNET_break (NULL == entry->transport_op_); | ||
659 | GNUNET_break (NULL == entry->core_handle); | ||
660 | GNUNET_break (NULL == entry->core_op); | ||
496 | GNUNET_break (NULL == entry->cfg); | 661 | GNUNET_break (NULL == entry->cfg); |
497 | GNUNET_assert (NULL == entry->cgh_qhead); | 662 | GNUNET_assert (NULL == entry->cgh_qhead); |
498 | GNUNET_assert (NULL == entry->cgh_qtail); | 663 | GNUNET_assert (NULL == entry->cgh_qtail); |
@@ -616,6 +781,46 @@ GST_cache_get_handle_transport (unsigned int peer_id, | |||
616 | 781 | ||
617 | 782 | ||
618 | /** | 783 | /** |
784 | * Get a transport handle with the given configuration. If the handle is already | ||
785 | * cached before, it will be retured in the given callback; the peer_id is used to lookup in the | ||
786 | * cache. If not a new operation is started to open the transport handle and | ||
787 | * will be given in the callback when it is available. | ||
788 | * | ||
789 | * @param peer_id the index of the peer | ||
790 | * @param cfg the configuration with which the transport handle has to be | ||
791 | * created if it was not present in the cache | ||
792 | * @param cb the callback to notify when the transport handle is available | ||
793 | * @param cb_cls the closure for the above callback | ||
794 | * @param target the peer identify of the peer whose connection to our TRANSPORT | ||
795 | * subsystem will be notified through the connect_notify_cb. Can be NULL | ||
796 | * @param connect_notify_cb the callback to call when the given target peer is | ||
797 | * connected. This callback will only be called once or never again (in | ||
798 | * case the target peer cannot be connected). Can be NULL | ||
799 | * @param connect_notify_cb_cls the closure for the above callback | ||
800 | * @return the handle which can be used cancel or mark that the handle is no | ||
801 | * longer being used | ||
802 | */ | ||
803 | struct GSTCacheGetHandle * | ||
804 | GST_cache_get_handle_core (unsigned int peer_id, | ||
805 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
806 | GST_cache_callback cb, | ||
807 | void *cb_cls, | ||
808 | const struct GNUNET_PeerIdentity *target, | ||
809 | GST_cache_peer_connect_notify connect_notify_cb, | ||
810 | void *connect_notify_cb_cls) | ||
811 | { | ||
812 | struct GSTCacheGetHandle *cgh; | ||
813 | |||
814 | cgh = GNUNET_malloc (sizeof (struct GSTCacheGetHandle)); | ||
815 | cgh->cb = cb; | ||
816 | cgh->cb_cls = cb_cls; | ||
817 | cgh->type = CGT_CORE_HANDLE; | ||
818 | return cache_get_handle (peer_id, cgh, cfg, | ||
819 | target, connect_notify_cb, connect_notify_cb_cls); | ||
820 | } | ||
821 | |||
822 | |||
823 | /** | ||
619 | * Looks up in the hello cache and returns the HELLO of the given peer | 824 | * Looks up in the hello cache and returns the HELLO of the given peer |
620 | * | 825 | * |
621 | * @param peer_id the index of the peer whose HELLO has to be looked up | 826 | * @param peer_id the index of the peer whose HELLO has to be looked up |