Skip to content

Commit

Permalink
chg: [fleurcli/fleur] better memory mgmnt / error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
gallypette committed Sep 22, 2022
1 parent 9121752 commit 5b74057
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 61 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,17 @@ struct BloomFilter fleur_bloom_filter_from_file(FILE* f);
int fleur_add(BloomFilter * bf, char *buf, size_t buf_size);
int fleur_check(BloomFilter * bf, char *buf, size_t buf_size);
int fleur_join(BloomFilter * src, BloomFilter* dst);
int fleur_bloom_filter_to_file(BloomFilter * bf, FILE* of);
void fleur_set_data(BloomFilter * bf, char* buf, size_t buf_size );
void fleur_bloom_filter_to_file(BloomFilter * bf, FILE* of);
void fleur_fingerprint(BloomFilter * bf, char *buf, size_t buf_size, uint64_t **fingerprint);
void fleur_destroy_filter(BloomFilter * bf);
void fleur_print_header(header * h);
void fleur_print_filter(BloomFilter * bf);
int fleur_check_header(header * h);
```

# Fleur command line tool usage
```
NAME:
Expand Down
75 changes: 42 additions & 33 deletions fleur/fleur.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,32 @@
#include <string.h>
#include "fleur.h"

// fleur_destroy_filter frees the memory used by
// a bloom filter.
void fleur_destroy_filter(BloomFilter * bf){
free(bf->v);
}

// fleur_bloom_filter_to_file serializes a bloom filter to a file
// it receives a file descriptor
void fleur_bloom_filter_to_file(BloomFilter * bf, FILE* of){
// it receives a file descriptor, return 1 on success, 0 on error
int fleur_bloom_filter_to_file(BloomFilter * bf, FILE* of){
bf->version = (uint64_t) 1;
fwrite(&bf->version, sizeof(uint64_t), 1, of);
fwrite(&bf->h.n, sizeof(uint64_t), 1, of);
fwrite(&bf->h.p, sizeof(double), 1, of);
fwrite(&bf->h.k, sizeof(uint64_t), 1, of);
fwrite(&bf->h.m, sizeof(uint64_t), 1, of);
fwrite(&bf->h.N, sizeof(uint64_t), 1, of);
fwrite(bf->v, bf->M * sizeof(uint64_t), 1, of);
uint64_t ret = 1;
ret = fwrite(&bf->version, sizeof(uint64_t), 1, of);
ret = fwrite(&bf->h.n, sizeof(uint64_t), 1, of);
ret = fwrite(&bf->h.p, sizeof(double), 1, of);
ret = fwrite(&bf->h.k, sizeof(uint64_t), 1, of);
ret = fwrite(&bf->h.m, sizeof(uint64_t), 1, of);
ret = fwrite(&bf->h.N, sizeof(uint64_t), 1, of);
ret = fwrite(bf->v, bf->M * sizeof(uint64_t), 1, of);
// Data can be empty
fwrite(bf->Data, bf->datasize * sizeof(unsigned char), 1, of);
if (ret == 0) {
fprintf(stderr, "[ERROR] writing filter file.\n");
return 0;
}else{
return 1;
}
}

// fleur_set_data sets the data field of the bloom filter
Expand All @@ -35,16 +49,14 @@ struct BloomFilter fleur_bloom_filter_from_file(FILE* f){

size_t elements_read = fread(&h, sizeof(header), 1, f);
if(elements_read == 0){
fprintf(stderr, "Error reading filter file.\n");
fprintf(stderr, "[ERROR] reading filter file.\n");
bf.error = 1;
fclose(f);
return bf;
}

if (fleur_check_header(&h) != 1){
fprintf(stderr, "Incoherent header.\n");
fprintf(stderr, "[ERROR] Incoherent header.\n");
bf.error = 1;
fclose(f);
return bf;
}

Expand All @@ -53,9 +65,8 @@ struct BloomFilter fleur_bloom_filter_from_file(FILE* f){
// Get data size
int err = fseek(f, 0, SEEK_END);
if(err!=0){
fprintf(stderr, "Cannot seek in binary file.\n");
fprintf(stderr, "[ERROR] Cannot seek in binary file.\n");
bf.error = 1;
fclose(f);
return bf;
}
long size = ftell(f);
Expand All @@ -69,9 +80,8 @@ struct BloomFilter fleur_bloom_filter_from_file(FILE* f){
bf.v = calloc(bf.M, sizeof(uint64_t));
elements_read = fread(bf.v, sizeof(uint64_t), bf.M, f);
if(elements_read == 0){
fprintf(stderr, "Cannot load bitarray.\n");
fprintf(stderr, "[ERROR] Cannot load bitarray.\n");
bf.error = 1;
fclose(f);
return bf;
}

Expand All @@ -81,9 +91,8 @@ struct BloomFilter fleur_bloom_filter_from_file(FILE* f){
bf.Data = calloc(bf.datasize + 1, sizeof(unsigned char));
elements_read = fread(bf.Data, sizeof(char), bf.datasize, f);
if(elements_read == 0){
fprintf(stderr, "Cannot load bloom filter metadata.\n");
fprintf(stderr, "[ERROR] Cannot load bloom filter metadata.\n");
bf.error = 1;
fclose(f);
return bf;
}
bf.Data[bf.datasize] = '\0';
Expand Down Expand Up @@ -178,27 +187,27 @@ int fleur_check(BloomFilter * bf, char *buf, size_t buf_size) {
int fleur_join(BloomFilter* src, BloomFilter* dst){
uint64_t i;
if (src->h.n != dst->h.n) {
fprintf(stderr, "Filters characteristics mismatch - cannot join.\n");
fprintf(stderr, "[ERROR] Filters characteristics mismatch - cannot join.\n");
return 0;
}
if (src->h.p != dst->h.p) {
fprintf(stderr, "Filters characteristics mismatch - cannot join.\n");
fprintf(stderr, "[ERROR] Filters characteristics mismatch - cannot join.\n");
return 0;
}
if (src->h.k != dst->h.k) {
fprintf(stderr, "Filters characteristics mismatch - cannot join.\n");
fprintf(stderr, "[ERROR] Filters characteristics mismatch - cannot join.\n");
return 0;
}
if (src->h.m != dst->h.m) {
fprintf(stderr, "Filters characteristics mismatch - cannot join.\n");
fprintf(stderr, "[ERROR] Filters characteristics mismatch - cannot join.\n");
return 0;
}
if (src->M != dst->M) {
fprintf(stderr, "Filters characteristics mismatch - cannot join.\n");
fprintf(stderr, "[ERROR] Filters characteristics mismatch - cannot join.\n");
return 0;
}
if ((dst->h.N + src->h.N) > dst->h.n) {
fprintf(stderr, "Destination Filter is full.\n");
fprintf(stderr, "[ERROR] Destination Filter is full.\n");
return -1;
}
for (uint64_t i; i < dst->M; i++){
Expand Down Expand Up @@ -245,43 +254,43 @@ void fleur_print_header(header * h){
// fleur_check_printer check a BloomFilter's header for inconsistencies
int fleur_check_header(header * h){
if (h->version != 1){
fprintf(stderr, "Current filter version not supported.\n");
fprintf(stderr, "[ERROR] Current filter version not supported.\n");
return 0;
}
// 0111111111111111111111111111111111111111111111111111111111111111b
uint64_t maxint = 9223372036854775807;
if (h->k >= maxint){
fprintf(stderr, "value of k (number of hash functions) is too high.\n");
fprintf(stderr, "[ERROR] value of k (number of hash functions) is too high.\n");
return 0;
}
if (h->p <= __DBL_EPSILON__){
fprintf(stderr, "p is too small.\n");
fprintf(stderr, "[ERROR] p is too small.\n");
return 0;
}
if (h->p > 1){
fprintf(stderr, "p is more than one.\n");
fprintf(stderr, "[ERROR] p is more than one.\n");
return 0;
}
if (h->N > h->n){
fprintf(stderr, "incoherent filter.\n");
fprintf(stderr, "[ERROR] incoherent filter.\n");
return 0;
}
uint64_t tmp_m = fabs(ceil((double)(h->n) * log(h->p) / pow(log(2.0), 2.0)));
if (tmp_m != h->m){
fprintf(stderr, "incoherent filter.\n");
fprintf(stderr, "[ERROR] incoherent filter.\n");
return 0;
}
uint64_t tmp_k = ceil(log(2) * h->m / h->n );
if (tmp_k != h->k){
fprintf(stderr, "incoherent filter values.\n");
fprintf(stderr, "[ERROR] incoherent filter values.\n");
return 0;
}
return 1;
}

// fleur_printer_filter prints a BloomFilter's details
void fleur_print_filter(BloomFilter * bf){
printf("Filter details:\n n: %lu \n p: %f\n k: %lu \n m: %lu \n N: %lu \n M: %lu\n Data: %s.",
printf("Filter details:\n n: %lu \n p: %f\n k: %lu \n m: %lu \n N: %lu \n M: %lu\n Data: %s.\n",
bf->h.n,
bf->h.p,
bf->h.k,
Expand Down
8 changes: 5 additions & 3 deletions fleur/fleur.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ typedef struct BloomFilter {
//number of 64-bit integers (generated automatically)
uint64_t M;

// bit array - dynamic
// bit array - on the heap
uint64_t *v;

// arbitrary data that we can attach to the filter - dynamic
// arbitrary data that we can attach to the filter - on the stack
unsigned char *Data;

// has the bloom filter been modified?
Expand All @@ -50,10 +50,12 @@ struct BloomFilter fleur_bloom_filter_from_file(FILE* f);
int fleur_add(BloomFilter * bf, char *buf, size_t buf_size);
int fleur_check(BloomFilter * bf, char *buf, size_t buf_size);
int fleur_join(BloomFilter * src, BloomFilter* dst);
int fleur_bloom_filter_to_file(BloomFilter * bf, FILE* of);
void fleur_set_data(BloomFilter * bf, char* buf, size_t buf_size );
void fleur_bloom_filter_to_file(BloomFilter * bf, FILE* of);
void fleur_fingerprint(BloomFilter * bf, char *buf, size_t buf_size, uint64_t **fingerprint);

void fleur_destroy_filter(BloomFilter * bf);

void fleur_print_header(header * h);
void fleur_print_filter(BloomFilter * bf);
int fleur_check_header(header * h);
20 changes: 14 additions & 6 deletions fleurcli/fleurcli.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ int main(int argc, char* argv[])

bf = fleur_bloom_filter_from_file(in);
if (bf.error != 0){
fclose(in);
return EXIT_FAILURE;
}
fclose(in);
Expand All @@ -145,8 +146,8 @@ int main(int argc, char* argv[])
printf("%s", buffer);
}
}
fleur_destroy_filter(&bf);
free(buffer);
free(bf.v);
free(bloom_path);
free(bloom_path_dst);
free(mode_str);
Expand All @@ -163,14 +164,14 @@ int main(int argc, char* argv[])
}
fleur_bloom_filter_to_file(&bf, f);
fclose(f);
free(bf.v);
fleur_destroy_filter(&bf);
free(bloom_path);
free(bloom_path_dst);
free(mode_str);
return EXIT_SUCCESS;
case show:
fleur_print_filter(&bf);
free(bf.v);
fleur_destroy_filter(&bf);
free(bloom_path);
free(bloom_path_dst);
free(mode_str);
Expand All @@ -182,9 +183,10 @@ int main(int argc, char* argv[])
fprintf(stderr, "[ERROR] %s", strerror(errno));
return EXIT_FAILURE;
}
// TODO
fleur_bloom_filter_to_file(&bf, f);
fleur_destroy_filter(&bf);
fclose(f);
free(bf.v);
free(bloom_path);
free(bloom_path_dst);
free(mode_str);
Expand Down Expand Up @@ -214,8 +216,7 @@ int main(int argc, char* argv[])
fleur_bloom_filter_to_file(&bf, f);
fclose(f);
free(totalread);
free(bf.v);
free(bf.Data);
fleur_destroy_filter(&bf);
}
free(bloom_path);
free(bloom_path_dst);
Expand All @@ -237,6 +238,8 @@ int main(int argc, char* argv[])

bf = fleur_bloom_filter_from_file(in);
if (bf.error != 0){
fclose(in);
fleur_destroy_filter(&bf);
return EXIT_FAILURE;
}
fclose(in);
Expand Down Expand Up @@ -270,7 +273,12 @@ int main(int argc, char* argv[])
return EXIT_FAILURE;
}

// TODO
int ret = 1;
fleur_bloom_filter_to_file(&dst, fdst);
if (ret != 1){
fprintf(stderr, "[ERROR] %s", strerror(errno));
}
fclose(fdst);
return EXIT_SUCCESS;

Expand Down
34 changes: 17 additions & 17 deletions test/suite_2/test_fleur.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,22 +88,26 @@ void test_reading_full(void)
BloomFilter bf = fleur_bloom_filter_from_file(infull);
TEST_ASSERT_EQUAL_INT(0, bf.error);
TEST_ASSERT_EQUAL_UINT64(450, bf.M);
// TEST_ASSERT_EQUAL_STRING("toto\n", my_bloom->Data);
fleur_print_filter(&bf);
// free(bf.v);
// free(bf.Data);
fleur_destroy_filter(&bf);

// hang2 p above 1
BloomFilter bf1 = fleur_bloom_filter_from_file(hang2);
TEST_ASSERT_EQUAL_INT (1, bf1.error);
fleur_destroy_filter(&bf1);
}

void test_writing(void){
const char* path = "./writing-test.bloom";
int ret = 1;
FILE* f = fopen(path, "wb");
BloomFilter bf;
struct tester *test = GenerateExampleFilter(&bf, 1000, 0.001, 100);
fleur_bloom_filter_to_file(test->bf, f);
ret = fleur_bloom_filter_to_file(test->bf, f);
if (ret != 1) {
TEST_FAIL_MESSAGE("Error writing filter to file.");
}
fleur_destroy_filter(&bf);
fclose(f);
}

Expand All @@ -120,7 +124,7 @@ void test_fingerprint(void){
break;
}
}
free(bf.v);
fleur_destroy_filter(&bf);
free(fp);
}

Expand Down Expand Up @@ -151,9 +155,9 @@ void test_initialize(void){
fleur_print_filter(&bf);
fleur_print_filter(&bf1);
fleur_print_filter(&bf2);
free(bf.v);
free(bf1.v);
free(bf2.v);
fleur_destroy_filter(&bf);
fleur_destroy_filter(&bf1);
fleur_destroy_filter(&bf2);
}

//This tests the checking of values against a given filter
Expand All @@ -172,10 +176,10 @@ void test_checking(void) {
if (fleur_check(test->bf, str, strlen(str)) == 1) {
TEST_FAIL_MESSAGE("This value is not in the filter!");
}
free(test->bf->v);
for (int i = 0; i < samples; i++){
free(test->buf[i]);
}
fleur_destroy_filter(test->bf);
free(test);
}

Expand All @@ -188,12 +192,9 @@ void test_joining(void) {
TEST_ASSERT_EQUAL_INT (-1, fleur_join(&j2, &j1));
TEST_ASSERT_EQUAL_INT (0, fleur_join(&j0, &j1));
TEST_ASSERT_EQUAL_INT (1, fleur_join(&j3, &j1));
free(j0.v);
free(j0.Data);
free(j1.v);
free(j1.Data);
free(j2.v);
free(j2.Data);
fleur_destroy_filter(&j0);
fleur_destroy_filter(&j1);
fleur_destroy_filter(&j2);
}

void setUp() {
Expand Down Expand Up @@ -236,8 +237,7 @@ void tearDown() {
fclose(infull);
fclose(hang0);
fclose(hang1);
// hang2 closed on error by fleur_bloom_filter_from_file
// fclose(hang2);
fclose(hang2);
fclose(join1);
fclose(join2);
fclose(join3);
Expand Down

0 comments on commit 5b74057

Please sign in to comment.