diff --git a/index.js b/index.js index 85efd2e..c360d56 100644 --- a/index.js +++ b/index.js @@ -4,6 +4,14 @@ var levelProxy = require('level-proxy'); var net = require('net'); var fs = require('fs'); var path = require('path'); +var has = require('has'); +var manifest = require('level-manifest')({ + methods: { + _iteratorCreate: { type: 'async' }, + _iteratorNext: { type: 'async' }, + _iteratorEnd: { type: 'async' } + } +}); module.exports = function (dir, opts) { var proxy = levelProxy(); @@ -27,8 +35,40 @@ function withProxy (proxy, dir, opts) { db.removeListener('error', onerror); var server = net.createServer(function (stream) { - stream.on('error', function (err) {}); + var iterators = {}; + if (!db.methods) db.methods = {}; + + db.methods._iteratorCreate = { type: 'async' }; + db._iteratorCreate = function (ix, opts) { + iterators[ix] = (db.iterator && db.iterator(opts)) + || (db.db && db.db.iterator && db.db.iterator(opts)) + ; + }; + + db.methods._iteratorNext = { type: 'async' }; + db._iteratorNext = function (ix, cb) { + if (!has(iterators, ix)) cb(new Error('no such iterator')) + else iterators[ix].next(function (err, key, value) { + cb(err, key, value); + }) + }; + + db.methods._iteratorEnd = { type: 'async' }; + db._iteratorEnd = function (ix, cb) { + if (!has(iterators, ix)) cb(new Error('no such iterator')) + else iterators[ix].end(cb) + }; + + stream.on('error', function (err) { cleanup() }); + stream.once('end', cleanup); stream.pipe(multilevel.server(db)).pipe(stream); + + function cleanup () { + Object.keys(iterators).forEach(function (ix) { + iterators[ix].end(); + }); + iterators = null; + } }); server.listen(sockfile); @@ -58,7 +98,17 @@ function withProxy (proxy, dir, opts) { } function createStream () { - var xdb = multilevel.client(); + var xdb = multilevel.client(manifest); + + var iteratorIx = 0; + xdb.iterator = function (opts) { + var ix = iteratorIx ++; + xdb._iteratorCreate(ix, opts); + + return { next: next, end: end }; + function next (cb) { xdb._iteratorNext(ix, cb) } + function end (cb) { xdb._iteratorEnd(ix, cb) } + }; (function connect () { var stream = net.connect(sockfile); diff --git a/package.json b/package.json index 3b76b59..87f0892 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,10 @@ "description": "open a leveldb handle multiple times", "main": "index.js", "dependencies": { + "has": "0.0.1", "level": "~0.18.0", "level-proxy": "^1.0.0", - "multilevel": "~5.5.0" + "multilevel": "^6.0.0" }, "devDependencies": { "tape": "~2.3.2" diff --git a/test/sublevel.js b/test/sublevel.js new file mode 100644 index 0000000..30ab73d --- /dev/null +++ b/test/sublevel.js @@ -0,0 +1,41 @@ +var test = require('tape'); +var level = require('../'); +var path = require('path'); +var sub = require('level-sublevel'); +var os = require('os'); +var tmpdir = os.tmpdir ? os.tmpdir() : os.tmpDir(); +var datadir = path.join(tmpdir, 'level-party-' + Math.random()); + +test('sublevel', function (t) { + t.plan(6); + var db = level(datadir); + var sdb = sub(db); + var a = sdb.sublevel('aaa', { valueEncoding: 'json' }); + var b = sdb.sublevel('bbb', { valueEncoding: 'json' }); + + var value = Math.floor(Math.random() * 100000); + + a.put('x', value, function (err) { + t.ifError(err); + + a.get('x', function (err, x) { + t.ifError(err); + t.equal(x, value); + }); + b.get('x', function (err, x) { + t.ok(err); + }); + + a.createReadStream().on('data', function (row) { + t.deepEqual(row.key, 'x'); + t.deepEqual(row.value, value); + }); + b.createReadStream().on('data', function (row) { + t.fail('b should not have rows'); + }); + }); + + t.on('end', function () { + db.close(); + }); +});