Skip to content

Commit

Permalink
Add (de)serialization for block filters
Browse files Browse the repository at this point in the history
Partialy addresses #20
  • Loading branch information
jbapple committed Sep 15, 2022
1 parent 63c6c27 commit 0b13e23
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 0 deletions.
4 changes: 4 additions & 0 deletions c/include/filter/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ double libfilter_block_fpp(double ndv, double bytes);
uint64_t libfilter_block_capacity(uint64_t bytes, double fpp);
void libfilter_block_zero_out(libfilter_block *);
bool libfilter_block_equals(const libfilter_block *, const libfilter_block *);
void libfilter_block_serialize(const libfilter_block *, char *);
// returns < 0 on error
int libfilter_block_deserialize(uint64_t size_in_bytes, const char *from,
libfilter_block *to);
// Essentially the inverse operation of libfilter_block_bytes_needed: returns the heap
// space used by the data in the filter
inline uint64_t libfilter_block_size_in_bytes(const libfilter_block *);
Expand Down
27 changes: 27 additions & 0 deletions c/lib/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,33 @@ uint64_t libfilter_block_bytes_needed(double ndv, double fpp) {
return libfilter_block_bytes_needed_detail(ndv, fpp, 32, 8, 32);
}

void libfilter_block_serialize(const libfilter_block *from, char *to) {
for (uint64_t i = 0; i < from->num_buckets_; ++i) {
for (int j = 0; j < 8; ++j) {
uint32_t x = from->block_.block[8 * i + j];
for (int k = 0; k < 4; ++k) {
to[32 * i + 4 * j + k] = x >> (8 * k);
}
}
}
}

// returns < 0 on error
int libfilter_block_deserialize(uint64_t size_in_bytes, const char* from,
libfilter_block* to) {
const int result = libfilter_block_init(size_in_bytes, to);
if (result < 0) return result;
for (uint64_t i = 0; i < size_in_bytes / 32; ++i) {
for (int j = 0; j < 8; ++j) {
uint32_t *x = &to->block_.block[8 * i + j];
for (int k = 0; k < 4; ++k) {
*x |= ((uint32_t)(unsigned char)from[32 * i + 4 * j + k]) << (8 * k);
}
}
}
return result;
}

__attribute__((visibility("hidden"))) int libfilter_block_calloc(uint64_t heap_space,
uint64_t bucket_bytes,
libfilter_block* here) {
Expand Down
12 changes: 12 additions & 0 deletions cpp/extras/test/block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,3 +245,15 @@ TEST(FreezeTest, FreezeTest) {
EXPECT_TRUE(ftcf.FindHash(keys[i]));
}
}

TEST(SerDeTest, SerDeTest) {
Rand r;
for (size_t size = 1; size < 1 << 20; size *= 2) {
BlockFilter f = BlockFilter::CreateWithNdvFpp(size, 0.01);
for (size_t i = 0; i < size; ++i) f.InsertHash(r());
vector<char> serialized(f.SizeInBytes());
f.Serialize(serialized.data());
auto g = BlockFilter::Deserialize(f.SizeInBytes(), serialized.data());
EXPECT_TRUE(f == g) << size << ", " << f.SizeInBytes() << ", " << g.SizeInBytes();
}
}
11 changes: 11 additions & 0 deletions cpp/include/filter/block.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,17 @@ class GenericBF {
const uint64_t bytes = libfilter_block_bytes_needed(ndv, fpp);
return CreateWithBytes(bytes);
}

void Serialize(char * to) const {
libfilter_block_serialize(&payload_, to);
}

static GenericBF Deserialize(uint64_t size_in_bytes, const char* from) {
GenericBF result{size_in_bytes};
result.~GenericBF();
libfilter_block_deserialize(size_in_bytes, from, &result.payload_);
return result;
}
};

template <void (*INSERT_HASH)(uint64_t, libfilter_block*),
Expand Down

0 comments on commit 0b13e23

Please sign in to comment.