bloom: cleanup instantiation.
This commit is contained in:
parent
dbaae30700
commit
65ab296d2e
@ -2199,7 +2199,7 @@ function FilterLoadPacket(filter) {
|
||||
|
||||
Packet.call(this);
|
||||
|
||||
this.filter = filter || new Bloom(0, 0, 0, -1);
|
||||
this.filter = filter || new Bloom();
|
||||
}
|
||||
|
||||
util.inherits(FilterLoadPacket, Packet);
|
||||
|
||||
@ -14,6 +14,7 @@ var StaticWriter = require('./staticwriter');
|
||||
var encoding = require('./encoding');
|
||||
var sum32 = murmur3.sum32;
|
||||
var mul32 = murmur3.mul32;
|
||||
var DUMMY = new Buffer(0);
|
||||
|
||||
/*
|
||||
* Constants
|
||||
@ -29,6 +30,7 @@ var LN2 = 0.6931471805599453094172321214581765680755001343602552;
|
||||
* @param {Number|Bufer} size - Filter size in bits, or filter itself.
|
||||
* @param {Number} n - Number of hash functions.
|
||||
* @param {Number} tweak - Seed value.
|
||||
* @param {Number|String} - Update type.
|
||||
* @property {Buffer} filter
|
||||
* @property {Number} size
|
||||
* @property {Number} n
|
||||
@ -40,27 +42,14 @@ function Bloom(size, n, tweak, update) {
|
||||
if (!(this instanceof Bloom))
|
||||
return new Bloom(size, n, tweak, update);
|
||||
|
||||
if (Buffer.isBuffer(size)) {
|
||||
this.filter = size;
|
||||
this.size = this.filter.length * 8;
|
||||
} else {
|
||||
this.size = size - (size % 8);
|
||||
this.filter = new Buffer(this.size / 8);
|
||||
this.reset();
|
||||
}
|
||||
this.filter = DUMMY;
|
||||
this.size = 0;
|
||||
this.n = 0;
|
||||
this.tweak = 0;
|
||||
this.update = Bloom.flags.NONE;
|
||||
|
||||
if (tweak == null || tweak === -1)
|
||||
tweak = (Math.random() * 0x100000000) >>> 0;
|
||||
|
||||
if (update == null || update === -1)
|
||||
update = Bloom.flags.NONE;
|
||||
|
||||
if (typeof update === 'string')
|
||||
update = Bloom.flags[update.toUpperCase()];
|
||||
|
||||
this.n = n;
|
||||
this.tweak = tweak;
|
||||
this.update = update;
|
||||
if (size != null)
|
||||
this.fromOptions(size, n, tweak, update);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -117,6 +106,68 @@ Bloom.MAX_BLOOM_FILTER_SIZE = 36000;
|
||||
|
||||
Bloom.MAX_HASH_FUNCS = 50;
|
||||
|
||||
/**
|
||||
* Inject properties from options.
|
||||
* @private
|
||||
* @param {Number|Bufer} size - Filter size in bits, or filter itself.
|
||||
* @param {Number} n - Number of hash functions.
|
||||
* @param {Number} tweak - Seed value.
|
||||
* @param {Number|String} - Update type.
|
||||
* @returns {Bloom}
|
||||
*/
|
||||
|
||||
Bloom.prototype.fromOptions = function fromOptions(size, n, tweak, update) {
|
||||
var filter;
|
||||
|
||||
if (Buffer.isBuffer(size)) {
|
||||
filter = size;
|
||||
size = filter.length * 8;
|
||||
} else {
|
||||
assert(typeof size === 'number', '`size` must be a number.');
|
||||
assert(size > 0, '`size` must be greater than zero.');
|
||||
size -= size % 8;
|
||||
filter = new Buffer(size / 8);
|
||||
filter.fill(0);
|
||||
}
|
||||
|
||||
if (tweak == null || tweak === -1)
|
||||
tweak = (Math.random() * 0x100000000) >>> 0;
|
||||
|
||||
if (update == null || update === -1)
|
||||
update = Bloom.flags.NONE;
|
||||
|
||||
if (typeof update === 'string') {
|
||||
update = Bloom.flags[update.toUpperCase()];
|
||||
assert(update != null, 'Unknown update flag.');
|
||||
}
|
||||
|
||||
assert(size > 0, '`size` must be greater than zero.');
|
||||
assert(n > 0, '`n` must be greater than zero.');
|
||||
assert(typeof tweak === 'number', '`tweak` must be a number.');
|
||||
assert(Bloom.flagsByVal[update], 'Unknown update flag.');
|
||||
|
||||
this.filter = filter;
|
||||
this.size = size;
|
||||
this.n = n;
|
||||
this.tweak = tweak;
|
||||
this.update = update;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate bloom filter from options.
|
||||
* @param {Number|Bufer} size - Filter size in bits, or filter itself.
|
||||
* @param {Number} n - Number of hash functions.
|
||||
* @param {Number} tweak - Seed value.
|
||||
* @param {Number|String} - Update type.
|
||||
* @returns {Bloom}
|
||||
*/
|
||||
|
||||
Bloom.fromOptions = function fromOptions(size, n, tweak, update) {
|
||||
return new Bloom().fromOptions(size, n, tweak, update);
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the mumur3 hash on data.
|
||||
* @param {Buffer} val
|
||||
@ -203,11 +254,11 @@ Bloom.prototype.added = function added(val, enc) {
|
||||
|
||||
/**
|
||||
* Create a filter from a false positive rate.
|
||||
* @param {Number} items - Expeected number of items.
|
||||
* @param {Number} items - Expected number of items.
|
||||
* @param {Number} rate - False positive rate (0.0-1.0).
|
||||
* @param {Number|String} update
|
||||
* @example
|
||||
* bcoin.bloom.fromRate(800000, 0.01, 'none');
|
||||
* Bloom.fromRate(800000, 0.0001, 'none');
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
@ -219,7 +270,7 @@ Bloom.fromRate = function fromRate(items, rate, update) {
|
||||
if (update !== -1)
|
||||
size = Math.min(size, Bloom.MAX_BLOOM_FILTER_SIZE * 8);
|
||||
|
||||
n = ((size / items * LN2) | 0) || 1;
|
||||
n = Math.max(1, size / items * LN2);
|
||||
|
||||
if (update !== -1)
|
||||
n = Math.min(n, Bloom.MAX_HASH_FUNCS);
|
||||
@ -285,7 +336,7 @@ Bloom.prototype.fromReader = function fromReader(br) {
|
||||
this.n = br.readU32();
|
||||
this.tweak = br.readU32();
|
||||
this.update = br.readU8();
|
||||
assert(Bloom.flagsByVal[this.update] != null, 'Bad filter flag.');
|
||||
assert(Bloom.flagsByVal[this.update] != null, 'Unknown update flag.');
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -332,31 +383,76 @@ Bloom.fromRaw = function fromRaw(data, enc) {
|
||||
*/
|
||||
|
||||
function RollingFilter(items, rate) {
|
||||
var logRate, max;
|
||||
|
||||
if (!(this instanceof RollingFilter))
|
||||
return new RollingFilter(items, rate);
|
||||
|
||||
logRate = Math.log(rate);
|
||||
|
||||
this.entries = 0;
|
||||
this.generation = 1;
|
||||
this.n = 0;
|
||||
this.limit = 0;
|
||||
this.size = 0;
|
||||
this.items = 0;
|
||||
this.tweak = 0;
|
||||
this.filter = DUMMY;
|
||||
|
||||
this.n = Math.max(1, Math.min(Math.round(logRate / Math.log(0.5)), 50));
|
||||
this.limit = (items + 1) / 2 | 0;
|
||||
|
||||
max = this.limit * 3;
|
||||
this.size = -1 * this.n * max / Math.log(1.0 - Math.exp(logRate / this.n));
|
||||
this.size = Math.ceil(this.size);
|
||||
|
||||
this.items = ((this.size + 63) / 64 | 0) << 1;
|
||||
|
||||
this.tweak = (Math.random() * 0x100000000) >>> 0;
|
||||
|
||||
this.filter = new Buffer(this.items * 8);
|
||||
this.filter.fill(0);
|
||||
if (items != null)
|
||||
this.fromRate(items, rate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject properties from items and FPR.
|
||||
* @private
|
||||
* @param {Number} items - Expected number of items.
|
||||
* @param {Number} rate - False positive rate (0.0-1.0).
|
||||
* @returns {RollingFilter}
|
||||
*/
|
||||
|
||||
RollingFilter.prototype.fromRate = function fromRate(items, rate) {
|
||||
var logRate, max, n, limit, size, items, tweak, filter;
|
||||
|
||||
assert(typeof items === 'number', '`items` must be a number.');
|
||||
assert(items > 0, '`items` must be greater than zero.');
|
||||
assert(typeof rate === 'number', '`rate` must be a number.');
|
||||
assert(rate >= 0, '`rate` must be positive.');
|
||||
|
||||
logRate = Math.log(rate);
|
||||
|
||||
n = Math.max(1, Math.min(Math.round(logRate / Math.log(0.5)), 50));
|
||||
limit = (items + 1) / 2 | 0;
|
||||
|
||||
max = limit * 3;
|
||||
size = -1 * n * max / Math.log(1.0 - Math.exp(logRate / n));
|
||||
size = Math.ceil(size);
|
||||
|
||||
items = ((size + 63) / 64 | 0) << 1;
|
||||
items >>>= 0;
|
||||
|
||||
tweak = (Math.random() * 0x100000000) >>> 0;
|
||||
|
||||
filter = new Buffer(items * 8);
|
||||
filter.fill(0);
|
||||
|
||||
this.n = n;
|
||||
this.limit = limit;
|
||||
this.size = size;
|
||||
this.items = items;
|
||||
this.tweak = tweak;
|
||||
this.filter = filter;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate rolling filter from items and FPR.
|
||||
* @param {Number} items - Expected number of items.
|
||||
* @param {Number} rate - False positive rate (0.0-1.0).
|
||||
* @returns {RollingFilter}
|
||||
*/
|
||||
|
||||
RollingFilter.fromRate = function fromRate(items, rate) {
|
||||
return new RollingFilter().fromRate(items, rate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the mumur3 hash on data.
|
||||
* @param {Buffer} val
|
||||
|
||||
Loading…
Reference in New Issue
Block a user