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