diff --git a/lib/bcoin/ldb.js b/lib/bcoin/ldb.js index 6d2e2087..7d7fc71f 100644 --- a/lib/bcoin/ldb.js +++ b/lib/bcoin/ldb.js @@ -102,7 +102,15 @@ function LowlevelUp(file, options) { this.db = this.db.db; } - this.db.open(options, function(err) { + this.binding = this.db; + this.hasBinding = false; + + if (this.db.binding) { + this.binding = this.db.binding; + this.hasBinding = true; + } + + this.binding.open(options, function(err) { if (err) return self.emit('error', err); @@ -125,7 +133,7 @@ LowlevelUp.prototype.get = function get(key, options, callback) { callback = options; options = {}; } - return this.db.get(key, options, function(err, result) { + return this.binding.get(key, options, function(err, result) { if (err) { if (err.notFound || /not\s*found/i.test(err.message)) { err.notFound = true; @@ -138,34 +146,88 @@ LowlevelUp.prototype.get = function get(key, options, callback) { }; LowlevelUp.prototype.close = function close(callback) { - return this.db.close(callback); + return this.binding.close(callback); }; LowlevelUp.prototype.put = function put(key, value, options, callback) { - return this.db.put(key, value, options, callback); + return this.binding.put(key, value, options, callback); }; LowlevelUp.prototype.del = function del(key, options, callback) { - return this.db.del(key, options, callback); + return this.binding.del(key, options, callback); }; LowlevelUp.prototype.batch = function batch(ops, options, callback) { if (!ops) - return this.db.batch(); - return this.db.batch(ops, options, callback); + return this.binding.batch(); + return this.binding.batch(ops, options, callback); }; LowlevelUp.prototype.iterator = function iterator(options) { + if (this.hasBinding) + return new Iterator(this.binding, options); return this.db.iterator(options); }; LowlevelUp.prototype.getProperty = function getProperty(name) { - if (!this.db.getProperty) + if (!this.binding.getProperty) return null; - return this.db.getProperty(name); + return this.binding.getProperty(name); }; LowlevelUp.prototype.approximateSize = function approximateSize(start, end, callback) { - return this.db.approximateSize(start, end, callback); + return this.binding.approximateSize(start, end, callback); +}; + +function Iterator(binding, options) { + this.binding = binding.iterator(options); + this.cache = null; + this.finished = false; +} + +Iterator.prototype.seek = function (key) { + if (typeof key !== 'string') + throw new Error('seek requires a string key'); + if (this.cache) + this.cache.length = 0; + this.cache = null; + this.binding.seek(key); +}; + +Iterator.prototype.next = function next(callback) { + var self = this; + var key, value; + + if (this.cache && this.cache.length) { + key = this.cache.pop(); + value = this.cache.pop(); + + utils.nextTick(function() { + callback(null, key, value); + }); + } else if (this.finished) { + utils.nextTick(function() { + callback(); + }); + } else { + this.binding.next(function(err, array, finished) { + if (err) + return callback(err); + + self.cache = array; + self.finished = finished; + self.next(callback); + }); + } + + return this; +}; + +Iterator.prototype.end = function end(callback) { + if (this.cache) + this.cache.length = 0; + delete this.cache; + this.binding.end(callback); + delete this.binding; };