Deletable Bloom Filter Gone Wrong
A Bloom filter chosen for a cache-invalidation feature adds a remove() method that silently corrupts membership queries.
Codejavascript
// Requirement: track 'seen' URLs, but ALSO support un-seeing (removing) URLs.
// Team picked a standard Bloom filter and bolted on remove().
class BloomFilter {
constructor(size, k) {
this.size = size;
this.k = k;
this.bits = new Uint8Array(size);
}
_hashes(str) {
const out = [];
let h1 = 2166136261;
let h2 = 5381;
for (const ch of str) {
h1 = (h1 ^ ch.charCodeAt(0)) * 16777619 >>> 0;
h2 = ((h2 << 5) + h2 + ch.charCodeAt(0)) >>> 0;
}
for (let i = 0; i < this.k; i++) {
out.push((h1 + i * h2) % this.size);
}
return out;
}
add(str) {
for (const idx of this._hashes(str)) this.bits[idx] = 1;
}
remove(str) {
for (const idx of this._hashes(str)) this.bits[idx] = 0;
}
has(str) {
return this._hashes(str).every(idx => this.bits[idx] === 1);
}
}Given the requirement to support removal, what is the bug in this implementation?