From 9d44401f3b7be2439dc27b36b0244704868772bd Mon Sep 17 00:00:00 2001 From: Yichao 'Peak' Ji Date: Mon, 19 Dec 2016 12:05:10 +0800 Subject: [PATCH] iterator seek ignores highWaterMark for once --- src/iterator.cc | 7 +++++++ src/iterator.h | 1 + test/iterator-test.js | 46 ++++++++++++++++++++++++++++++++----------- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/iterator.cc b/src/iterator.cc index 234a0a46..e7d297c5 100644 --- a/src/iterator.cc +++ b/src/iterator.cc @@ -58,6 +58,7 @@ Iterator::Iterator ( count = 0; target = NULL; seeking = false; + landed = false; nexting = false; ended = false; endWorker = NULL; @@ -215,6 +216,11 @@ bool Iterator::IteratorNext (std::vector >& result.push_back(std::make_pair(key, value)); size = size + key.size() + value.size(); + if (!landed) { + landed = true; + return true; + } + if (size > highWaterMark) return true; @@ -273,6 +279,7 @@ NAN_METHOD(Iterator::Seek) { dbIterator->Seek(*iterator->target); iterator->seeking = true; + iterator->landed = false; if (iterator->OutOfRange(iterator->target)) { if (iterator->reverse) { diff --git a/src/iterator.h b/src/iterator.h index 801d9e88..07e67cd6 100644 --- a/src/iterator.h +++ b/src/iterator.h @@ -64,6 +64,7 @@ class Iterator : public Nan::ObjectWrap { leveldb::Slice* target; std::string* end; bool seeking; + bool landed; bool reverse; bool keys; bool values; diff --git a/test/iterator-test.js b/test/iterator-test.js index 82ec4d2c..49d2e2a7 100644 --- a/test/iterator-test.js +++ b/test/iterator-test.js @@ -98,17 +98,41 @@ make('reverse seek from invalid range', function (db, t, done) { }) }) -make('iterator seek resets state', function (db, t, done) { - var ite = db.iterator() - ite.next(function (err, key, value) { - t.error(err, 'no error from next()') - t.equal(key.toString(), 'one', 'key matches') - t.ok(ite.cache, 'has cached items') - t.equal(ite.finished, true, 'finished') - ite.seek('two') - t.notOk(ite.cache, 'cache is removed') - t.equal(ite.finished, false, 'resets finished state') - ite.end(done) +make('iterator optimized for seek', function (db, t, done) { + var batch = db.batch() + batch.put('a', 1) + batch.put('b', 1) + batch.put('c', 1) + batch.put('d', 1) + batch.put('e', 1) + batch.put('f', 1) + batch.put('g', 1) + batch.write(function (err) { + var ite = db.iterator() + t.error(err, 'no error from batch') + ite.next(function (err, key, value) { + t.error(err, 'no error from next()') + t.equal(key.toString(), 'a', 'key matches') + t.equal(ite.cache.length, 0, "no cache") + ite.next(function (err, key, value) { + t.error(err, 'no error from next()') + t.equal(key.toString(), 'b', 'key matches') + t.ok(ite.cache.length > 0, "has cached items") + ite.seek('d') + t.notOk(ite.cache, 'cache is removed') + ite.next(function (err, key, value) { + t.error(err, 'no error from next()') + t.equal(key.toString(), 'd', 'key matches') + t.equal(ite.cache.length, 0, "no cache") + ite.next(function (err, key, value) { + t.error(err, 'no error from next()') + t.equal(key.toString(), 'e', 'key matches') + t.ok(ite.cache.length > 0, "has cached items") + done(); + }) + }) + }) + }) }) })