/** * Estimate set difference with two strata estimators, * i.e. arrays of IBFs. * Does not not modify its arguments. * * @param se1 first strata estimator * @param se2 second strata estimator * @return the estimated difference */ unsigned int strata_estimator_difference (const struct StrataEstimator *se1, const struct StrataEstimator *se2) { int i; int count; GNUNET_assert (se1->strata_count == se2->strata_count); count = 0; for (i = se1->strata_count - 1; i >= 0; i--) { struct InvertibleBloomFilter *diff; /* number of keys decoded from the ibf */ int ibf_count; /* FIXME: implement this without always allocating new IBFs */ diff = ibf_dup (se1->strata[i]); ibf_subtract (diff, se2->strata[i]); for (ibf_count = 0; GNUNET_YES; ibf_count++) { int more; more = ibf_decode (diff, NULL, NULL); if (GNUNET_NO == more) { count += ibf_count; break; } /* Estimate if decoding fails or would not terminate */ if ((GNUNET_SYSERR == more) || (ibf_count > diff->size)) { ibf_destroy (diff); return count * (1 << (i + 1)); } } ibf_destroy (diff); } return count; }
static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_HashCode id; struct IBF_Key ibf_key; int i; int side; int res; struct GNUNET_TIME_Absolute start_time; struct GNUNET_TIME_Relative delta_time; set_a = GNUNET_CONTAINER_multihashmap_create (((asize == 0) ? 1 : (asize + csize)), GNUNET_NO); set_b = GNUNET_CONTAINER_multihashmap_create (((bsize == 0) ? 1 : (bsize + csize)), GNUNET_NO); set_c = GNUNET_CONTAINER_multihashmap_create (((csize == 0) ? 1 : csize), GNUNET_NO); key_to_hashcode = GNUNET_CONTAINER_multihashmap_create (((asize+bsize+csize == 0) ? 1 : (asize+bsize+csize)), GNUNET_NO); printf ("hash-num=%u, size=%u, #(A-B)=%u, #(B-A)=%u, #(A&B)=%u\n", hash_num, ibf_size, asize, bsize, csize); i = 0; while (i < asize) { GNUNET_CRYPTO_hash_create_random (random_quality, &id); if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_a, &id)) continue; GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (set_a, &id, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); register_hashcode (&id); i++; } i = 0; while (i < bsize) { GNUNET_CRYPTO_hash_create_random (random_quality, &id); if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_a, &id)) continue; if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_b, &id)) continue; GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (set_b, &id, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); register_hashcode (&id); i++; } i = 0; while (i < csize) { GNUNET_CRYPTO_hash_create_random (random_quality, &id); if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_a, &id)) continue; if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_b, &id)) continue; if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_c, &id)) continue; GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (set_c, &id, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); register_hashcode (&id); i++; } ibf_a = ibf_create (ibf_size, hash_num); ibf_b = ibf_create (ibf_size, hash_num); if ( (NULL == ibf_a) || (NULL == ibf_b) ) { /* insufficient memory */ GNUNET_break (0); GNUNET_SCHEDULER_shutdown (); return; } printf ("generated sets\n"); start_time = GNUNET_TIME_absolute_get (); GNUNET_CONTAINER_multihashmap_iterate (set_a, &insert_iterator, ibf_a); GNUNET_CONTAINER_multihashmap_iterate (set_b, &insert_iterator, ibf_b); GNUNET_CONTAINER_multihashmap_iterate (set_c, &insert_iterator, ibf_a); GNUNET_CONTAINER_multihashmap_iterate (set_c, &insert_iterator, ibf_b); delta_time = GNUNET_TIME_absolute_get_duration (start_time); printf ("encoded in: %s\n", GNUNET_STRINGS_relative_time_to_string (delta_time, GNUNET_NO)); ibf_subtract (ibf_a, ibf_b); start_time = GNUNET_TIME_absolute_get (); for (i = 0; i <= asize + bsize; i++) { res = ibf_decode (ibf_a, &side, &ibf_key); if (GNUNET_SYSERR == res) { printf ("decode failed, %u/%u elements left\n", GNUNET_CONTAINER_multihashmap_size (set_a) + GNUNET_CONTAINER_multihashmap_size (set_b), asize + bsize); return; } if (GNUNET_NO == res) { if ((0 == GNUNET_CONTAINER_multihashmap_size (set_b)) && (0 == GNUNET_CONTAINER_multihashmap_size (set_a))) { delta_time = GNUNET_TIME_absolute_get_duration (start_time); printf ("decoded successfully in: %s\n", GNUNET_STRINGS_relative_time_to_string (delta_time, GNUNET_NO)); } else { printf ("decode missed elements (should never happen)\n"); } return; } if (side == 1) iter_hashcodes (ibf_key, remove_iterator, set_a); if (side == -1) iter_hashcodes (ibf_key, remove_iterator, set_b); } printf("cyclic IBF, %u/%u elements left\n", GNUNET_CONTAINER_multihashmap_size (set_a) + GNUNET_CONTAINER_multihashmap_size (set_b), asize + bsize); }