49 #include <ndn-cxx/util/exception.hpp>
53 namespace be = boost::endian;
73 : m_compressionScheme(scheme)
76 size_t nEntries = expectedNumEntries + expectedNumEntries / 2;
78 size_t remainder = nEntries %
N_HASH;
80 nEntries += (
N_HASH - remainder);
83 m_hashTable.resize(nEntries);
91 if (3 * m_hashTable.size() != values.size()) {
92 NDN_THROW(
Error(
"Received IBF cannot be decoded!"));
95 for (
size_t i = 0; i < m_hashTable.size(); i++) {
97 if (values[i * 3] != 0) {
98 entry.
count = values[i * 3];
99 entry.
keySum = values[(i * 3) + 1];
100 entry.
keyCheck = values[(i * 3) + 2];
106 IBLT::update(
int plusOrMinus, uint32_t key)
108 size_t bucketsPerHash = m_hashTable.size() /
N_HASH;
110 for (
size_t i = 0; i <
N_HASH; i++) {
111 size_t startEntry = i * bucketsPerHash;
113 HashTableEntry& entry = m_hashTable.at(startEntry + (h % bucketsPerHash));
114 entry.
count += plusOrMinus;
140 for (
const auto& entry : peeled.m_hashTable) {
142 if (entry.
count == 1) {
146 negative.insert(entry.
keySum);
152 }
while (nErased > 0);
156 for (
const auto& entry : peeled.m_hashTable) {
168 BOOST_ASSERT(m_hashTable.size() == other.m_hashTable.size());
171 for (
size_t i = 0; i < m_hashTable.size(); i++) {
185 constexpr
size_t unitSize =
sizeof(m_hashTable[0].count) +
186 sizeof(m_hashTable[0].keySum) +
187 sizeof(m_hashTable[0].keyCheck);
189 size_t tableSize = unitSize * m_hashTable.size();
190 std::vector<uint8_t> table(tableSize);
192 for (
size_t i = 0; i < m_hashTable.size(); i++) {
193 uint32_t count = be::native_to_big(
static_cast<uint32_t
>(m_hashTable[i].count));
194 uint32_t keySum = be::native_to_big(
static_cast<uint32_t
>(m_hashTable[i].keySum));
195 uint32_t keyCheck = be::native_to_big(
static_cast<uint32_t
>(m_hashTable[i].keyCheck));
197 std::memcpy(&table[i * unitSize], &count,
sizeof(count));
198 std::memcpy(&table[(i * unitSize) + 4], &keySum,
sizeof(keySum));
199 std::memcpy(&table[(i * unitSize) + 8], &keyCheck,
sizeof(keyCheck));
202 auto compressed =
compress(m_compressionScheme, table);
203 name.append(ndn::name::Component(std::move(compressed)));
206 std::vector<uint32_t>
209 auto decompressedBuf =
decompress(m_compressionScheme, ibltName.value_bytes());
211 if (decompressedBuf->size() % 4 != 0) {
212 NDN_THROW(
Error(
"Received IBF cannot be decompressed correctly!"));
215 size_t n = decompressedBuf->size() / 4;
216 std::vector<uint32_t> values(n, 0);
218 for (
size_t i = 0; i < n; i++) {
220 std::memcpy(&t, &(*decompressedBuf)[i * 4],
sizeof(t));
221 values[i] = be::big_to_native(t);
232 if (iblt1HashTable.size() != iblt2HashTable.size()) {
236 size_t N = iblt1HashTable.size();
238 for (
size_t i = 0; i < N; i++) {
239 if (iblt1HashTable[i].count != iblt2HashTable[i].count ||
240 iblt1HashTable[i].keySum != iblt2HashTable[i].keySum ||
241 iblt1HashTable[i].keyCheck != iblt2HashTable[i].keyCheck)
251 return !(iblt1 == iblt2);
257 os <<
"count keySum keyCheckMatch\n";
Invertible Bloom Lookup Table (Invertible Bloom Filter)
bool listEntries(std::set< uint32_t > &positive, std::set< uint32_t > &negative) const
List all the entries in the IBLT.
std::vector< uint32_t > extractValueFromName(const ndn::name::Component &ibltName) const
Extracts IBLT from name component.
IBLT operator-(const IBLT &other) const
IBLT(size_t expectedNumEntries, CompressionScheme scheme)
constructor
void insert(uint32_t key)
const std::vector< HashTableEntry > & getHashTable() const
void initialize(const ndn::name::Component &ibltName)
Populate the hash table using the vector representation of IBLT.
void appendToName(ndn::Name &name) const
Appends self to name.
bool operator!=(const IBLT &iblt1, const IBLT &iblt2)
uint32_t murmurHash3(const void *key, size_t len, uint32_t seed)
constexpr size_t N_HASHCHECK
std::ostream & operator<<(std::ostream &os, const IBLT &iblt)
std::shared_ptr< ndn::Buffer > compress(CompressionScheme scheme, ndn::span< const uint8_t > buffer)
bool operator==(const IBLT &iblt1, const IBLT &iblt2)
std::shared_ptr< ndn::Buffer > decompress(CompressionScheme scheme, ndn::span< const uint8_t > buffer)