diff options
Diffstat (limited to 'src/namestore/gnunet-service-namestore.c')
-rw-r--r-- | src/namestore/gnunet-service-namestore.c | 277 |
1 files changed, 258 insertions, 19 deletions
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c index 9b6428872..b2cc826fd 100644 --- a/src/namestore/gnunet-service-namestore.c +++ b/src/namestore/gnunet-service-namestore.c | |||
@@ -243,6 +243,11 @@ struct ZoneMonitor | |||
243 | int in_first_iteration; | 243 | int in_first_iteration; |
244 | 244 | ||
245 | /** | 245 | /** |
246 | * Run again because we skipped an orphan | ||
247 | */ | ||
248 | int run_again; | ||
249 | |||
250 | /** | ||
246 | * Is there a store activity waiting for this monitor? We only raise the | 251 | * Is there a store activity waiting for this monitor? We only raise the |
247 | * flag when it happens and search the DLL for the store activity when we | 252 | * flag when it happens and search the DLL for the store activity when we |
248 | * had a limit increase. If we cannot find any waiting store activity at | 253 | * had a limit increase. If we cannot find any waiting store activity at |
@@ -335,6 +340,36 @@ struct NickCache | |||
335 | struct GNUNET_TIME_Absolute last_used; | 340 | struct GNUNET_TIME_Absolute last_used; |
336 | }; | 341 | }; |
337 | 342 | ||
343 | /** | ||
344 | * The default namestore ego | ||
345 | */ | ||
346 | struct EgoEntry | ||
347 | { | ||
348 | /** | ||
349 | * DLL | ||
350 | */ | ||
351 | struct EgoEntry *next; | ||
352 | |||
353 | /** | ||
354 | * DLL | ||
355 | */ | ||
356 | struct EgoEntry *prev; | ||
357 | |||
358 | /** | ||
359 | * Ego Identifier | ||
360 | */ | ||
361 | char *identifier; | ||
362 | |||
363 | /** | ||
364 | * Public key string | ||
365 | */ | ||
366 | char *keystring; | ||
367 | |||
368 | /** | ||
369 | * The Ego | ||
370 | */ | ||
371 | struct GNUNET_IDENTITY_Ego *ego; | ||
372 | }; | ||
338 | 373 | ||
339 | /** | 374 | /** |
340 | * We cache nick records to reduce DB load. | 375 | * We cache nick records to reduce DB load. |
@@ -357,6 +392,27 @@ static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg; | |||
357 | static struct GNUNET_STATISTICS_Handle *statistics; | 392 | static struct GNUNET_STATISTICS_Handle *statistics; |
358 | 393 | ||
359 | /** | 394 | /** |
395 | * Handle to the identity service | ||
396 | */ | ||
397 | static struct GNUNET_IDENTITY_Handle *identity_handle; | ||
398 | |||
399 | /** | ||
400 | * Indicator if we already have passed the first iteration if egos | ||
401 | */ | ||
402 | static int egos_collected = GNUNET_NO; | ||
403 | |||
404 | /** | ||
405 | * Ego list | ||
406 | */ | ||
407 | static struct EgoEntry *ego_head; | ||
408 | |||
409 | /** | ||
410 | * Ego list | ||
411 | */ | ||
412 | static struct EgoEntry *ego_tail; | ||
413 | |||
414 | |||
415 | /** | ||
360 | * Name of the database plugin | 416 | * Name of the database plugin |
361 | */ | 417 | */ |
362 | static char *db_lib_name; | 418 | static char *db_lib_name; |
@@ -406,6 +462,9 @@ static int cache_keys; | |||
406 | static void | 462 | static void |
407 | cleanup_task (void *cls) | 463 | cleanup_task (void *cls) |
408 | { | 464 | { |
465 | struct EgoEntry *ego_entry; | ||
466 | struct EgoEntry *ego_tmp; | ||
467 | |||
409 | (void) cls; | 468 | (void) cls; |
410 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n"); | 469 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n"); |
411 | if (NULL != monitor_nc) | 470 | if (NULL != monitor_nc) |
@@ -418,6 +477,20 @@ cleanup_task (void *cls) | |||
418 | GNUNET_STATISTICS_destroy (statistics, GNUNET_NO); | 477 | GNUNET_STATISTICS_destroy (statistics, GNUNET_NO); |
419 | statistics = NULL; | 478 | statistics = NULL; |
420 | } | 479 | } |
480 | if (NULL != identity_handle) | ||
481 | { | ||
482 | GNUNET_IDENTITY_disconnect (identity_handle); | ||
483 | identity_handle = NULL; | ||
484 | // FIXME cleanup EgoEntries | ||
485 | } | ||
486 | for (ego_entry = ego_head; NULL != ego_entry;) | ||
487 | { | ||
488 | ego_tmp = ego_entry; | ||
489 | ego_entry = ego_entry->next; | ||
490 | GNUNET_free (ego_tmp->identifier); | ||
491 | GNUNET_free (ego_tmp->keystring); | ||
492 | GNUNET_free (ego_tmp); | ||
493 | } | ||
421 | GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database)); | 494 | GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database)); |
422 | GNUNET_free (db_lib_name); | 495 | GNUNET_free (db_lib_name); |
423 | db_lib_name = NULL; | 496 | db_lib_name = NULL; |
@@ -436,6 +509,48 @@ free_store_activity (struct StoreActivity *sa) | |||
436 | GNUNET_free (sa); | 509 | GNUNET_free (sa); |
437 | } | 510 | } |
438 | 511 | ||
512 | static enum GNUNET_GenericReturnValue | ||
513 | is_orphaned (const struct GNUNET_IDENTITY_PrivateKey *zone) | ||
514 | { | ||
515 | struct EgoEntry *ego_entry; | ||
516 | struct GNUNET_IDENTITY_PublicKey pk; | ||
517 | char *keystring; | ||
518 | |||
519 | GNUNET_IDENTITY_key_get_public (zone, &pk); | ||
520 | keystring = GNUNET_IDENTITY_public_key_to_string (&pk); | ||
521 | |||
522 | for (ego_entry = ego_head; NULL != ego_entry; | ||
523 | ego_entry = ego_entry->next) | ||
524 | { | ||
525 | if (0 == strcmp (ego_entry->keystring, keystring)) | ||
526 | break; | ||
527 | } | ||
528 | if (NULL != ego_entry) | ||
529 | { | ||
530 | GNUNET_free (keystring); | ||
531 | return GNUNET_NO; | ||
532 | } | ||
533 | /*if (purge_orphans) | ||
534 | { | ||
535 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
536 | "Removing orphaned zone data for ego %s\n", | ||
537 | ego_entry->keystring); | ||
538 | res = GSN_database->delete_records (GSN_database->cls, | ||
539 | zone, | ||
540 | &emsg); | ||
541 | if (GNUNET_SYSERR == res) | ||
542 | { | ||
543 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
544 | "Error removing orphaned zone data: %s\n", emsg); | ||
545 | } | ||
546 | }*/ | ||
547 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
548 | "Found orphaned zone data for zone key %s\n", | ||
549 | keystring); | ||
550 | GNUNET_free (keystring); | ||
551 | return GNUNET_YES; | ||
552 | } | ||
553 | |||
439 | 554 | ||
440 | /** | 555 | /** |
441 | * Function called with the records for the #GNUNET_GNS_EMPTY_LABEL_AT | 556 | * Function called with the records for the #GNUNET_GNS_EMPTY_LABEL_AT |
@@ -1958,6 +2073,11 @@ struct ZoneIterationProcResult | |||
1958 | * Number of results left to be returned in this iteration. | 2073 | * Number of results left to be returned in this iteration. |
1959 | */ | 2074 | */ |
1960 | uint64_t limit; | 2075 | uint64_t limit; |
2076 | |||
2077 | /** | ||
2078 | * Skip a result and run again unless GNUNET_NO | ||
2079 | */ | ||
2080 | int run_again; | ||
1961 | }; | 2081 | }; |
1962 | 2082 | ||
1963 | 2083 | ||
@@ -1999,8 +2119,15 @@ zone_iterate_proc (void *cls, | |||
1999 | GNUNET_break (0); | 2119 | GNUNET_break (0); |
2000 | return; | 2120 | return; |
2001 | } | 2121 | } |
2002 | proc->limit--; | ||
2003 | proc->zi->seq = seq; | 2122 | proc->zi->seq = seq; |
2123 | if (GNUNET_YES == is_orphaned (zone_key)) | ||
2124 | { | ||
2125 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2126 | "Skipping orphaned zone data\n"); | ||
2127 | proc->run_again = GNUNET_YES; | ||
2128 | return; | ||
2129 | } | ||
2130 | proc->limit--; | ||
2004 | send_lookup_response_with_filter (proc->zi->nc, | 2131 | send_lookup_response_with_filter (proc->zi->nc, |
2005 | proc->zi->request_id, | 2132 | proc->zi->request_id, |
2006 | zone_key, | 2133 | zone_key, |
@@ -2032,18 +2159,23 @@ run_zone_iteration_round (struct ZoneIteration *zi, uint64_t limit) | |||
2032 | (unsigned long long) zi->seq); | 2159 | (unsigned long long) zi->seq); |
2033 | proc.zi = zi; | 2160 | proc.zi = zi; |
2034 | proc.limit = limit; | 2161 | proc.limit = limit; |
2162 | proc.run_again = GNUNET_YES; | ||
2035 | start = GNUNET_TIME_absolute_get (); | 2163 | start = GNUNET_TIME_absolute_get (); |
2036 | GNUNET_break (GNUNET_SYSERR != | 2164 | while (GNUNET_YES == proc.run_again) |
2037 | nc->GSN_database->iterate_records (nc->GSN_database->cls, | 2165 | { |
2038 | (GNUNET_YES == | 2166 | proc.run_again = GNUNET_NO; |
2039 | GNUNET_is_zero ( | 2167 | GNUNET_break (GNUNET_SYSERR != |
2040 | &zi->zone)) | 2168 | nc->GSN_database->iterate_records (nc->GSN_database->cls, |
2169 | (GNUNET_YES == | ||
2170 | GNUNET_is_zero ( | ||
2171 | &zi->zone)) | ||
2041 | ? NULL | 2172 | ? NULL |
2042 | : &zi->zone, | 2173 | : &zi->zone, |
2043 | zi->seq, | 2174 | zi->seq, |
2044 | limit, | 2175 | proc.limit, |
2045 | &zone_iterate_proc, | 2176 | &zone_iterate_proc, |
2046 | &proc)); | 2177 | &proc)); |
2178 | } | ||
2047 | duration = GNUNET_TIME_absolute_get_duration (start); | 2179 | duration = GNUNET_TIME_absolute_get_duration (start); |
2048 | duration = GNUNET_TIME_relative_divide (duration, limit - proc.limit); | 2180 | duration = GNUNET_TIME_relative_divide (duration, limit - proc.limit); |
2049 | GNUNET_STATISTICS_set (statistics, | 2181 | GNUNET_STATISTICS_set (statistics, |
@@ -2256,6 +2388,13 @@ monitor_iterate_cb (void *cls, | |||
2256 | "Monitor notifications sent", | 2388 | "Monitor notifications sent", |
2257 | 1, | 2389 | 1, |
2258 | GNUNET_NO); | 2390 | GNUNET_NO); |
2391 | if (GNUNET_YES == is_orphaned (zone_key)) | ||
2392 | { | ||
2393 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2394 | "Skipping orphaned zone data\n"); | ||
2395 | zm->run_again = GNUNET_YES; | ||
2396 | return; | ||
2397 | } | ||
2259 | zm->limit--; | 2398 | zm->limit--; |
2260 | zm->iteration_cnt--; | 2399 | zm->iteration_cnt--; |
2261 | send_lookup_response (zm->nc, 0, zone_key, name, rd_count, rd); | 2400 | send_lookup_response (zm->nc, 0, zone_key, name, rd_count, rd); |
@@ -2319,13 +2458,18 @@ monitor_iteration_next (void *cls) | |||
2319 | zm->iteration_cnt = zm->limit / 2; /* leave half for monitor events */ | 2458 | zm->iteration_cnt = zm->limit / 2; /* leave half for monitor events */ |
2320 | else | 2459 | else |
2321 | zm->iteration_cnt = zm->limit; /* use it all */ | 2460 | zm->iteration_cnt = zm->limit; /* use it all */ |
2322 | ret = nc->GSN_database->iterate_records (nc->GSN_database->cls, | 2461 | zm->run_again = GNUNET_YES; |
2323 | (GNUNET_YES == GNUNET_is_zero ( | 2462 | while (GNUNET_YES == zm->run_again) |
2324 | &zm->zone)) ? NULL : &zm->zone, | 2463 | { |
2325 | zm->seq, | 2464 | zm->run_again = GNUNET_NO; |
2326 | zm->iteration_cnt, | 2465 | ret = nc->GSN_database->iterate_records (nc->GSN_database->cls, |
2327 | &monitor_iterate_cb, | 2466 | (GNUNET_YES == GNUNET_is_zero ( |
2328 | zm); | 2467 | &zm->zone)) ? NULL : &zm->zone, |
2468 | zm->seq, | ||
2469 | zm->iteration_cnt, | ||
2470 | &monitor_iterate_cb, | ||
2471 | zm); | ||
2472 | } | ||
2329 | if (GNUNET_SYSERR == ret) | 2473 | if (GNUNET_SYSERR == ret) |
2330 | { | 2474 | { |
2331 | GNUNET_SERVICE_client_drop (zm->nc->client); | 2475 | GNUNET_SERVICE_client_drop (zm->nc->client); |
@@ -2339,7 +2483,6 @@ monitor_iteration_next (void *cls) | |||
2339 | } | 2483 | } |
2340 | } | 2484 | } |
2341 | 2485 | ||
2342 | |||
2343 | /** | 2486 | /** |
2344 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT message | 2487 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT message |
2345 | * | 2488 | * |
@@ -2398,6 +2541,99 @@ handle_monitor_next (void *cls, const struct ZoneMonitorNextMessage *nm) | |||
2398 | } | 2541 | } |
2399 | } | 2542 | } |
2400 | 2543 | ||
2544 | static void | ||
2545 | ego_callback (void *cls, | ||
2546 | struct GNUNET_IDENTITY_Ego *ego, | ||
2547 | void **ctx, | ||
2548 | const char *identifier) | ||
2549 | { | ||
2550 | struct EgoEntry *ego_entry; | ||
2551 | struct GNUNET_SERVICE_Handle *service = cls; | ||
2552 | struct GNUNET_IDENTITY_PublicKey pk; | ||
2553 | |||
2554 | if ((NULL == ego) && (GNUNET_NO == egos_collected)) | ||
2555 | { | ||
2556 | egos_collected = GNUNET_YES; | ||
2557 | GNUNET_SERVICE_resume (service); | ||
2558 | return; | ||
2559 | } | ||
2560 | if (NULL == ego) | ||
2561 | { | ||
2562 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
2563 | "Called with NULL ego\n"); | ||
2564 | return; | ||
2565 | } | ||
2566 | if ((GNUNET_NO == egos_collected) && | ||
2567 | (NULL != identifier)) | ||
2568 | { | ||
2569 | ego_entry = GNUNET_new (struct EgoEntry); | ||
2570 | GNUNET_IDENTITY_ego_get_public_key (ego, &pk); | ||
2571 | ego_entry->keystring = GNUNET_IDENTITY_public_key_to_string (&pk); | ||
2572 | ego_entry->ego = ego; | ||
2573 | ego_entry->identifier = GNUNET_strdup (identifier); | ||
2574 | GNUNET_CONTAINER_DLL_insert_tail (ego_head, | ||
2575 | ego_tail, | ||
2576 | ego_entry); | ||
2577 | return; | ||
2578 | } | ||
2579 | /* Ego renamed or added */ | ||
2580 | if (identifier != NULL) | ||
2581 | { | ||
2582 | for (ego_entry = ego_head; NULL != ego_entry; | ||
2583 | ego_entry = ego_entry->next) | ||
2584 | { | ||
2585 | if (ego_entry->ego == ego) | ||
2586 | { | ||
2587 | /* Rename */ | ||
2588 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
2589 | "Renaming ego %s->%s\n", ego_entry->identifier, | ||
2590 | identifier); | ||
2591 | GNUNET_free (ego_entry->identifier); | ||
2592 | ego_entry->identifier = GNUNET_strdup (identifier); | ||
2593 | break; | ||
2594 | } | ||
2595 | } | ||
2596 | if (NULL == ego_entry) | ||
2597 | { | ||
2598 | /* Add */ | ||
2599 | ego_entry = GNUNET_new (struct EgoEntry); | ||
2600 | GNUNET_IDENTITY_ego_get_public_key (ego, &pk); | ||
2601 | ego_entry->keystring = GNUNET_IDENTITY_public_key_to_string (&pk); | ||
2602 | ego_entry->ego = ego; | ||
2603 | ego_entry->identifier = GNUNET_strdup (identifier); | ||
2604 | GNUNET_CONTAINER_DLL_insert_tail (ego_head, | ||
2605 | ego_tail, | ||
2606 | ego_entry); | ||
2607 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
2608 | "Added ego %s\n", ego_entry->identifier); | ||
2609 | } | ||
2610 | } | ||
2611 | else | ||
2612 | { | ||
2613 | /* Delete */ | ||
2614 | for (ego_entry = ego_head; NULL != ego_entry; | ||
2615 | ego_entry = ego_entry->next) | ||
2616 | { | ||
2617 | if (ego_entry->ego == ego) | ||
2618 | break; | ||
2619 | } | ||
2620 | if (NULL == ego_entry) | ||
2621 | return; /* Not found */ | ||
2622 | |||
2623 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
2624 | "Removing ego %s\n", ego_entry->identifier); | ||
2625 | GNUNET_CONTAINER_DLL_remove (ego_head, | ||
2626 | ego_tail, | ||
2627 | ego_entry); | ||
2628 | GNUNET_free (ego_entry->identifier); | ||
2629 | GNUNET_free (ego_entry->keystring); | ||
2630 | GNUNET_free (ego_entry); | ||
2631 | return; | ||
2632 | } | ||
2633 | |||
2634 | } | ||
2635 | |||
2636 | |||
2401 | 2637 | ||
2402 | /** | 2638 | /** |
2403 | * Process namestore requests. | 2639 | * Process namestore requests. |
@@ -2413,7 +2649,6 @@ run (void *cls, | |||
2413 | { | 2649 | { |
2414 | char *database; | 2650 | char *database; |
2415 | (void) cls; | 2651 | (void) cls; |
2416 | (void) service; | ||
2417 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n"); | 2652 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n"); |
2418 | cache_keys = | 2653 | cache_keys = |
2419 | GNUNET_CONFIGURATION_get_value_yesno (cfg, "namestore", "CACHE_KEYS"); | 2654 | GNUNET_CONFIGURATION_get_value_yesno (cfg, "namestore", "CACHE_KEYS"); |
@@ -2443,6 +2678,10 @@ run (void *cls, | |||
2443 | GNUNET_SCHEDULER_add_now (&cleanup_task, NULL); | 2678 | GNUNET_SCHEDULER_add_now (&cleanup_task, NULL); |
2444 | return; | 2679 | return; |
2445 | } | 2680 | } |
2681 | egos_collected = GNUNET_NO; | ||
2682 | /** Suspend until we have all egos */ | ||
2683 | GNUNET_SERVICE_suspend (service); | ||
2684 | identity_handle = GNUNET_IDENTITY_connect (cfg, &ego_callback, service); | ||
2446 | GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL); | 2685 | GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL); |
2447 | } | 2686 | } |
2448 | 2687 | ||