END_TEST START_TEST(test_sbf_close_does_flush) { bloom_sbf_params params = SBF_DEFAULT_PARAMS; params.initial_capacity = 1e3; params.fp_probability = 1e-4; nextfile next; next.format = "/tmp/mmap_close.%d.data"; next.num = 0; bloom_sbf sbf; int res = sbf_from_filters(¶ms, sbf_make_callback, &next, 0, NULL, &sbf); fail_unless(res == 0); char buf[100]; for (int i=0;i<2000;i++) { snprintf((char*)&buf, 100, "foobar%d", i); sbf_add(&sbf, (char*)&buf); } fail_unless(sbf_close(&sbf) == 0); bloom_bitmap maps[2]; bitmap_from_filename("/tmp/mmap_close.0.data", get_size("/tmp/mmap_close.0.data"), 1, 1, SHARED, (bloom_bitmap*)&maps); bitmap_from_filename("/tmp/mmap_close.1.data", get_size("/tmp/mmap_close.1.data"), 1, 1, SHARED, ((bloom_bitmap*)&maps)+1); bloom_bloomfilter filters[2]; bf_from_bitmap((bloom_bitmap*)&maps, 1, 0, (bloom_bloomfilter*)&filters); bf_from_bitmap(((bloom_bitmap*)&maps)+1, 1, 0, ((bloom_bloomfilter*)&filters)+1); bloom_bloomfilter **filter_map = calloc(2, sizeof(bloom_bloomfilter*)); filter_map[0] = (bloom_bloomfilter*)&filters; filter_map[1] = ((bloom_bloomfilter*)&filters)+1; res = sbf_from_filters(¶ms, sbf_make_callback, &next, 2, filter_map, &sbf); fail_unless(res == 0); fail_unless(sbf_size(&sbf) == 2000); fail_unless(sbf_total_capacity(&sbf) == 5*1e3); for (int i=0;i<2000;i++) { snprintf((char*)&buf, 100, "foobar%d", i); res = sbf_contains(&sbf, (char*)&buf); fail_unless(res == 1); } unlink("/tmp/mmap_close.0.data"); unlink("/tmp/mmap_close.1.data"); }
END_TEST START_TEST(sbf_fp_prob) { bloom_sbf_params params = SBF_DEFAULT_PARAMS; params.initial_capacity = 1e4; params.fp_probability = 0.01; bloom_sbf sbf; int res = sbf_from_filters(¶ms, NULL, NULL, 0, NULL, &sbf); fail_unless(res == 0); char buf[100]; int num_wrong = 0; int wrong_per[5] = {0, 0, 0, 0, 0}; for (int i=0;i<1e6;i++) { snprintf((char*)&buf, 100, "ZibZab__%d", i*i); res = sbf_add(&sbf, (char*)&buf); if (res == 0) { num_wrong++; wrong_per[sbf.num_filters-1]++; } } fail_unless(sbf.num_filters == 5); fail_unless(num_wrong > 1000); // Expected error rate fail_unless(num_wrong < 10000); // Expected error rate }
END_TEST START_TEST(sbf_add_filter) { bloom_sbf_params params = SBF_DEFAULT_PARAMS; params.initial_capacity = 1e3; params.fp_probability = 1e-4; bloom_sbf sbf; int res = sbf_from_filters(¶ms, NULL, NULL, 0, NULL, &sbf); fail_unless(res == 0); // Check all the keys get added char buf[100]; for (int i=0;i<2000;i++) { snprintf((char*)&buf, 100, "foobar%d", i); res = sbf_add(&sbf, (char*)&buf); fail_unless(res == 1); } fail_unless(sbf_size(&sbf) == 2000); fail_unless(sbf.num_filters == 2); fail_unless(sbf_total_capacity(&sbf) == 5*1e3); // Check all the keys exist for (int i=0;i<2000;i++) { snprintf((char*)&buf, 100, "foobar%d", i); res = sbf_contains(&sbf, (char*)&buf); fail_unless(res == 1); } }
END_TEST START_TEST(test_sbf_flush_close) { bloom_sbf_params params = SBF_DEFAULT_PARAMS; params.initial_capacity = 1e3; params.fp_probability = 1e-4; bloom_sbf sbf; int res = sbf_from_filters(¶ms, NULL, NULL, 0, NULL, &sbf); fail_unless(res == 0); res = sbf_flush(&sbf); fail_unless(res == 0); res = sbf_close(&sbf); fail_unless(res == 0); }
END_TEST START_TEST(sbf_add_filter_2) { bloom_sbf_params params = SBF_DEFAULT_PARAMS; params.initial_capacity = 1e3; params.fp_probability = 1e-5; bloom_sbf sbf; int res = sbf_from_filters(¶ms, NULL, NULL, 0, NULL, &sbf); fail_unless(res == 0); // Check all the keys get added char buf[100]; for (int i=0;i<10000;i++) { snprintf((char*)&buf, 100, "foobar%d", i); res = sbf_add(&sbf, (char*)&buf); fail_unless(res == 1); } fail_unless(sbf_size(&sbf) == 10000); fail_unless(sbf.num_filters == 3); fail_unless(sbf_total_capacity(&sbf) == 21*1e3); // Check all the keys exist for (int i=0;i<10000;i++) { snprintf((char*)&buf, 100, "foobar%d", i); res = sbf_contains(&sbf, (char*)&buf); fail_unless(res == 1); } // Byte size should be greater than a static filter of the same config bloom_filter_params config_params = {0, 0, 21e3, 1e-4}; bf_params_for_capacity(&config_params); uint64_t total_size = sbf_total_byte_size(&sbf); fail_unless(total_size > config_params.bytes); fail_unless(total_size < 2 * config_params.bytes); }
/** * Internal method to create the SBF */ static int create_sbf(bloom_filter *f, int num, bloom_bloomfilter **filters) { // Setup the SBF params bloom_sbf_params params = { f->filter_config.initial_capacity, f->filter_config.default_probability, f->filter_config.scale_size, f->filter_config.probability_reduction }; // Create the SBF f->sbf = malloc(sizeof(bloom_sbf)); int res = sbf_from_filters(¶ms, bloomf_sbf_callback, f, num, filters, (bloom_sbf*)f->sbf); // Handle a failure if (res != 0) { syslog(LOG_ERR, "Failed to create SBF: %s. Err: %d", f->filter_name, res); free((bloom_sbf*)f->sbf); f->sbf = NULL; } else { syslog(LOG_INFO, "Loaded SBF: %s. Num filters: %d.", f->filter_name, num); } return res; }