diff options
author | Christian Grothoff <christian@grothoff.org> | 2014-07-12 20:29:25 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2014-07-12 20:29:25 +0000 |
commit | d1248e6a3d5603b4176dd67d7af720ac5d459126 (patch) | |
tree | 9e1f5f5fdf379c76d308e7ed91292a9b4d92fc7d /src/fs/fs_search.c | |
parent | a0c135cba1d033ea9cb04a6aa3ec269d82769fc2 (diff) | |
download | gnunet-d1248e6a3d5603b4176dd67d7af720ac5d459126.tar.gz gnunet-d1248e6a3d5603b4176dd67d7af720ac5d459126.zip |
fix #3446
Diffstat (limited to 'src/fs/fs_search.c')
-rw-r--r-- | src/fs/fs_search.c | 125 |
1 files changed, 101 insertions, 24 deletions
diff --git a/src/fs/fs_search.c b/src/fs/fs_search.c index 7e4e38b27..d4f0770e3 100644 --- a/src/fs/fs_search.c +++ b/src/fs/fs_search.c | |||
@@ -542,14 +542,16 @@ process_ksk_result (struct GNUNET_FS_SearchContext *sc, | |||
542 | GNUNET_assert (NULL != sc); | 542 | GNUNET_assert (NULL != sc); |
543 | GNUNET_FS_uri_to_key (uri, &key); | 543 | GNUNET_FS_uri_to_key (uri, &key); |
544 | if (GNUNET_SYSERR == | 544 | if (GNUNET_SYSERR == |
545 | GNUNET_CONTAINER_multihashmap_get_multiple (ent->results, &key, | 545 | GNUNET_CONTAINER_multihashmap_get_multiple (ent->results, |
546 | &key, | ||
546 | &test_result_present, | 547 | &test_result_present, |
547 | (void *) uri)) | 548 | (void *) uri)) |
548 | return; /* duplicate result */ | 549 | return; /* duplicate result */ |
549 | /* try to find search result in master map */ | 550 | /* try to find search result in master map */ |
550 | grc.sr = NULL; | 551 | grc.sr = NULL; |
551 | grc.uri = uri; | 552 | grc.uri = uri; |
552 | GNUNET_CONTAINER_multihashmap_get_multiple (sc->master_result_map, &key, | 553 | GNUNET_CONTAINER_multihashmap_get_multiple (sc->master_result_map, |
554 | &key, | ||
553 | &get_result_present, &grc); | 555 | &get_result_present, &grc); |
554 | sr = grc.sr; | 556 | sr = grc.sr; |
555 | is_new = (NULL == sr) || (sr->mandatory_missing > 0); | 557 | is_new = (NULL == sr) || (sr->mandatory_missing > 0); |
@@ -571,16 +573,34 @@ process_ksk_result (struct GNUNET_FS_SearchContext *sc, | |||
571 | { | 573 | { |
572 | GNUNET_CONTAINER_meta_data_merge (sr->meta, meta); | 574 | GNUNET_CONTAINER_meta_data_merge (sr->meta, meta); |
573 | } | 575 | } |
576 | GNUNET_break (GNUNET_OK == | ||
577 | GNUNET_CONTAINER_multihashmap_put (ent->results, | ||
578 | &sr->key, | ||
579 | sr, | ||
580 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
581 | |||
574 | koff = ent - sc->requests; | 582 | koff = ent - sc->requests; |
575 | GNUNET_assert ( (ent >= sc->requests) && (koff < sc->uri->data.ksk.keywordCount)); | 583 | GNUNET_assert ( (ent >= sc->requests) && |
584 | (koff < sc->uri->data.ksk.keywordCount)); | ||
576 | sr->keyword_bitmap[koff / 8] |= (1 << (koff % 8)); | 585 | sr->keyword_bitmap[koff / 8] |= (1 << (koff % 8)); |
577 | /* check if mandatory satisfied */ | 586 | /* check if mandatory satisfied */ |
578 | if (ent->mandatory) | 587 | if (1 == GNUNET_CONTAINER_multihashmap_size (ent->results)) |
579 | sr->mandatory_missing--; | 588 | { |
580 | else | 589 | if (ent->mandatory) |
581 | sr->optional_support++; | 590 | { |
591 | GNUNET_break (sr->mandatory_missing > 0); | ||
592 | sr->mandatory_missing--; | ||
593 | } | ||
594 | else | ||
595 | { | ||
596 | sr->optional_support++; | ||
597 | } | ||
598 | } | ||
582 | if (0 != sr->mandatory_missing) | 599 | if (0 != sr->mandatory_missing) |
600 | { | ||
601 | GNUNET_break (NULL == sr->client_info); | ||
583 | return; | 602 | return; |
603 | } | ||
584 | if (is_new) | 604 | if (is_new) |
585 | notify_client_chk_result (sc, sr); | 605 | notify_client_chk_result (sc, sr); |
586 | else | 606 | else |
@@ -649,7 +669,10 @@ process_sks_result (struct GNUNET_FS_SearchContext *sc, | |||
649 | GNUNET_FS_search_result_sync_ (sr); | 669 | GNUNET_FS_search_result_sync_ (sr); |
650 | GNUNET_FS_search_start_probe_ (sr); | 670 | GNUNET_FS_search_start_probe_ (sr); |
651 | /* notify client */ | 671 | /* notify client */ |
652 | notify_client_chk_result (sc, sr); | 672 | if (0 == sr->mandatory_missing) |
673 | notify_client_chk_result (sc, sr); | ||
674 | else | ||
675 | GNUNET_break (NULL == sr->client_info); | ||
653 | /* search for updates */ | 676 | /* search for updates */ |
654 | if (0 == strlen (id_update)) | 677 | if (0 == strlen (id_update)) |
655 | return; /* no updates */ | 678 | return; /* no updates */ |
@@ -746,11 +769,16 @@ process_kblock (struct GNUNET_FS_SearchContext *sc, | |||
746 | } | 769 | } |
747 | if (NULL == (uri = GNUNET_FS_uri_parse (&pt[1], &emsg))) | 770 | if (NULL == (uri = GNUNET_FS_uri_parse (&pt[1], &emsg))) |
748 | { | 771 | { |
749 | GNUNET_break_op (0); /* ublock malformed */ | 772 | if (GNUNET_FS_VERSION > 0x00090400) |
750 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 773 | { |
751 | _("Failed to parse URI `%s': %s\n"), | 774 | /* we broke this in 0x00090300, so don't bitch |
752 | &pt[1], | 775 | too loudly just one version up... */ |
753 | emsg); | 776 | GNUNET_break_op (0); /* ublock malformed */ |
777 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
778 | _("Failed to parse URI `%s': %s\n"), | ||
779 | &pt[1], | ||
780 | emsg); | ||
781 | } | ||
754 | GNUNET_free_non_null (emsg); | 782 | GNUNET_free_non_null (emsg); |
755 | return; | 783 | return; |
756 | } | 784 | } |
@@ -765,7 +793,10 @@ process_kblock (struct GNUNET_FS_SearchContext *sc, | |||
765 | GNUNET_FS_uri_destroy (uri); | 793 | GNUNET_FS_uri_destroy (uri); |
766 | return; | 794 | return; |
767 | } | 795 | } |
768 | process_ksk_result (sc, &sc->requests[i], uri, meta); | 796 | process_ksk_result (sc, |
797 | &sc->requests[i], | ||
798 | uri, | ||
799 | meta); | ||
769 | 800 | ||
770 | /* clean up */ | 801 | /* clean up */ |
771 | GNUNET_CONTAINER_meta_data_destroy (meta); | 802 | GNUNET_CONTAINER_meta_data_destroy (meta); |
@@ -1265,6 +1296,36 @@ search_start (struct GNUNET_FS_Handle *h, | |||
1265 | 1296 | ||
1266 | 1297 | ||
1267 | /** | 1298 | /** |
1299 | * Update the 'results' map for the individual keywords with the | ||
1300 | * results from the 'global' result set. | ||
1301 | * | ||
1302 | * @param cls closure, the `struct GNUNET_FS_SearchContext *` | ||
1303 | * @param key current key code | ||
1304 | * @param value value in the hash map, the `struct GNUNET_FS_SearchResult *` | ||
1305 | * @return #GNUNET_YES (we should continue to iterate) | ||
1306 | */ | ||
1307 | static int | ||
1308 | update_sre_result_maps (void *cls, | ||
1309 | const struct GNUNET_HashCode *key, | ||
1310 | void *value) | ||
1311 | { | ||
1312 | struct GNUNET_FS_SearchContext *sc = cls; | ||
1313 | struct GNUNET_FS_SearchResult *sr = value; | ||
1314 | unsigned int i; | ||
1315 | |||
1316 | for (i = 0; i < sc->uri->data.ksk.keywordCount; i++) | ||
1317 | if (0 != (sr->keyword_bitmap[i / 8] & (1 << (i % 8)))) | ||
1318 | GNUNET_break (GNUNET_OK == | ||
1319 | GNUNET_CONTAINER_multihashmap_put (sc->requests[i].results, | ||
1320 | &sr->key, | ||
1321 | sr, | ||
1322 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1323 | |||
1324 | return GNUNET_YES; | ||
1325 | } | ||
1326 | |||
1327 | |||
1328 | /** | ||
1268 | * Build the request and actually initiate the search using the | 1329 | * Build the request and actually initiate the search using the |
1269 | * GNUnet FS service. | 1330 | * GNUnet FS service. |
1270 | * | 1331 | * |
@@ -1295,9 +1356,9 @@ GNUNET_FS_search_start_searching_ (struct GNUNET_FS_SearchContext *sc) | |||
1295 | sre = &sc->requests[i]; | 1356 | sre = &sc->requests[i]; |
1296 | sre->keyword = GNUNET_strdup (keyword); | 1357 | sre->keyword = GNUNET_strdup (keyword); |
1297 | GNUNET_CRYPTO_ecdsa_public_key_derive (&anon_pub, | 1358 | GNUNET_CRYPTO_ecdsa_public_key_derive (&anon_pub, |
1298 | keyword, | 1359 | keyword, |
1299 | "fs-ublock", | 1360 | "fs-ublock", |
1300 | &sre->dpub); | 1361 | &sre->dpub); |
1301 | GNUNET_CRYPTO_hash (&sre->dpub, | 1362 | GNUNET_CRYPTO_hash (&sre->dpub, |
1302 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), | 1363 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), |
1303 | &sre->uquery); | 1364 | &sre->uquery); |
@@ -1306,6 +1367,9 @@ GNUNET_FS_search_start_searching_ (struct GNUNET_FS_SearchContext *sc) | |||
1306 | sc->mandatory_count++; | 1367 | sc->mandatory_count++; |
1307 | sre->results = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_NO); | 1368 | sre->results = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_NO); |
1308 | } | 1369 | } |
1370 | GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, | ||
1371 | &update_sre_result_maps, | ||
1372 | sc); | ||
1309 | } | 1373 | } |
1310 | sc->client = GNUNET_CLIENT_connect ("fs", sc->h->cfg); | 1374 | sc->client = GNUNET_CLIENT_connect ("fs", sc->h->cfg); |
1311 | if (NULL == sc->client) | 1375 | if (NULL == sc->client) |
@@ -1401,11 +1465,15 @@ search_result_suspend (void *cls, | |||
1401 | sr->update_search = NULL; | 1465 | sr->update_search = NULL; |
1402 | } | 1466 | } |
1403 | GNUNET_FS_search_stop_probe_ (sr); | 1467 | GNUNET_FS_search_stop_probe_ (sr); |
1404 | pi.status = GNUNET_FS_STATUS_SEARCH_RESULT_SUSPEND; | 1468 | if (0 == sr->mandatory_missing) |
1405 | pi.value.search.specifics.result_suspend.cctx = sr->client_info; | 1469 | { |
1406 | pi.value.search.specifics.result_suspend.meta = sr->meta; | 1470 | /* client is aware of search result, notify about suspension event */ |
1407 | pi.value.search.specifics.result_suspend.uri = sr->uri; | 1471 | pi.status = GNUNET_FS_STATUS_SEARCH_RESULT_SUSPEND; |
1408 | sr->client_info = GNUNET_FS_search_make_status_ (&pi, sc->h, sc); | 1472 | pi.value.search.specifics.result_suspend.cctx = sr->client_info; |
1473 | pi.value.search.specifics.result_suspend.meta = sr->meta; | ||
1474 | pi.value.search.specifics.result_suspend.uri = sr->uri; | ||
1475 | sr->client_info = GNUNET_FS_search_make_status_ (&pi, sc->h, sc); | ||
1476 | } | ||
1409 | GNUNET_break (NULL == sr->client_info); | 1477 | GNUNET_break (NULL == sr->client_info); |
1410 | GNUNET_free_non_null (sr->serialization); | 1478 | GNUNET_free_non_null (sr->serialization); |
1411 | GNUNET_FS_uri_destroy (sr->uri); | 1479 | GNUNET_FS_uri_destroy (sr->uri); |
@@ -1559,10 +1627,12 @@ search_result_stop (void *cls, | |||
1559 | sr->download->search = NULL; | 1627 | sr->download->search = NULL; |
1560 | sr->download->top = | 1628 | sr->download->top = |
1561 | GNUNET_FS_make_top (sr->download->h, | 1629 | GNUNET_FS_make_top (sr->download->h, |
1562 | &GNUNET_FS_download_signal_suspend_, sr->download); | 1630 | &GNUNET_FS_download_signal_suspend_, |
1631 | sr->download); | ||
1563 | if (NULL != sr->download->serialization) | 1632 | if (NULL != sr->download->serialization) |
1564 | { | 1633 | { |
1565 | GNUNET_FS_remove_sync_file_ (sc->h, GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD, | 1634 | GNUNET_FS_remove_sync_file_ (sc->h, |
1635 | GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD, | ||
1566 | sr->download->serialization); | 1636 | sr->download->serialization); |
1567 | GNUNET_free (sr->download->serialization); | 1637 | GNUNET_free (sr->download->serialization); |
1568 | sr->download->serialization = NULL; | 1638 | sr->download->serialization = NULL; |
@@ -1572,6 +1642,13 @@ search_result_stop (void *cls, | |||
1572 | GNUNET_FS_download_sync_ (sr->download); | 1642 | GNUNET_FS_download_sync_ (sr->download); |
1573 | sr->download = NULL; | 1643 | sr->download = NULL; |
1574 | } | 1644 | } |
1645 | if (0 != sr->mandatory_missing) | ||
1646 | { | ||
1647 | /* client is unaware of search result as | ||
1648 | it does not match required keywords */ | ||
1649 | GNUNET_break (NULL == sr->client_info); | ||
1650 | return GNUNET_OK; | ||
1651 | } | ||
1575 | pi.status = GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED; | 1652 | pi.status = GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED; |
1576 | pi.value.search.specifics.result_stopped.cctx = sr->client_info; | 1653 | pi.value.search.specifics.result_stopped.cctx = sr->client_info; |
1577 | pi.value.search.specifics.result_stopped.meta = sr->meta; | 1654 | pi.value.search.specifics.result_stopped.meta = sr->meta; |