Skip to content

Commit

Permalink
Merge pull request #323 from peakji/master
Browse files Browse the repository at this point in the history
Multiple seeks in ltgt range and support Buffers
  • Loading branch information
peakji committed Dec 18, 2016
2 parents 744e60b + 6a11623 commit 62aa908
Show file tree
Hide file tree
Showing 6 changed files with 288 additions and 30 deletions.
3 changes: 2 additions & 1 deletion README.md
Expand Up @@ -224,7 +224,8 @@ the `callback` function will be called with no arguments in any of the following

* the iterator comes to the end of the store
* the `end` key has been reached; or
* the `limit` has been reached
* the `limit` has been reached; or
* the last `seek()` was out of range

Otherwise, the `callback` function will be called with the following 3 arguments:

Expand Down
17 changes: 13 additions & 4 deletions iterator.js
Expand Up @@ -14,11 +14,20 @@ function Iterator (db, options) {

util.inherits(Iterator, AbstractIterator)

Iterator.prototype.seek = function (key) {
if (typeof key !== 'string')
throw new Error('seek requires a string key')
Iterator.prototype.seek = function (target) {
if (this._ended)
throw new Error('cannot call seek() after end()')
if (this._nexting)
throw new Error('cannot call seek() before next() has completed')

if (typeof target !== 'string' && !Buffer.isBuffer(target))
throw new Error('seek() requires a string or buffer key')
if (target.length == 0)
throw new Error('cannot seek() to an empty key')

this.cache = null
this.binding.seek(key)
this.binding.seek(target)
this.finished = false
}

Iterator.prototype._next = function (callback) {
Expand Down
2 changes: 2 additions & 0 deletions package.json
Expand Up @@ -39,6 +39,8 @@
"delayed": "~1.0.1",
"du": "~0.1.0",
"faucet": "0.0.1",
"iota-array": "~1.0.0",
"lexicographic-integer": "~1.1.0",
"mkfiletree": "~1.0.1",
"monotonic-timestamp": "~0.0.8",
"node-uuid": "~1.4.3",
Expand Down
93 changes: 78 additions & 15 deletions src/iterator.cc
Expand Up @@ -56,6 +56,7 @@ Iterator::Iterator (
options->snapshot = database->NewSnapshot();
dbIterator = NULL;
count = 0;
target = NULL;
seeking = false;
nexting = false;
ended = false;
Expand All @@ -64,6 +65,7 @@ Iterator::Iterator (

Iterator::~Iterator () {
delete options;
ReleaseTarget();
if (start != NULL) {
// Special case for `start` option: it won't be
// freed up by any of the delete calls below.
Expand Down Expand Up @@ -171,6 +173,38 @@ bool Iterator::Read (std::string& key, std::string& value) {
return false;
}

bool Iterator::OutOfRange (leveldb::Slice* target) {
if (lt != NULL) {
if (target->compare(*lt) >= 0)
return true;
} else if (lte != NULL) {
if (target->compare(*lte) > 0)
return true;
} else if (start != NULL && reverse) {
if (target->compare(*start) > 0)
return true;
}

if (end != NULL) {
int d = target->compare(*end);
if (reverse ? d < 0 : d > 0)
return true;
}

if (gt != NULL) {
if (target->compare(*gt) <= 0)
return true;
} else if (gte != NULL) {
if (target->compare(*gte) < 0)
return true;
} else if (start != NULL && !reverse) {
if (target->compare(*start) < 0)
return true;
}

return false;
}

bool Iterator::IteratorNext (std::vector<std::pair<std::string, std::string> >& result) {
size_t size = 0;
while(true) {
Expand Down Expand Up @@ -205,7 +239,19 @@ void Iterator::Release () {
database->ReleaseIterator(id);
}

void Iterator::ReleaseTarget () {
if (target != NULL) {

if (!target->empty())
delete[] target->data();

delete target;
target = NULL;
}
}

void checkEndCallback (Iterator* iterator) {
iterator->ReleaseTarget();
iterator->nexting = false;
if (iterator->endWorker != NULL) {
Nan::AsyncQueueWorker(iterator->endWorker);
Expand All @@ -215,35 +261,52 @@ void checkEndCallback (Iterator* iterator) {

NAN_METHOD(Iterator::Seek) {
Iterator* iterator = Nan::ObjectWrap::Unwrap<Iterator>(info.This());

iterator->ReleaseTarget();

v8::Local<v8::Value> targetBuffer = info[0].As<v8::Value>();
LD_STRING_OR_BUFFER_TO_COPY(_target, targetBuffer, target);
iterator->target = new leveldb::Slice(_targetCh_, _targetSz_);

iterator->GetIterator();
leveldb::Iterator* dbIterator = iterator->dbIterator;
Nan::Utf8String key(info[0]);

dbIterator->Seek(*key);
dbIterator->Seek(*iterator->target);
iterator->seeking = true;

if (dbIterator->Valid()) {
int cmp = dbIterator->key().compare(*key);
if (cmp > 0 && iterator->reverse) {
dbIterator->Prev();
} else if (cmp < 0 && !iterator->reverse) {
dbIterator->Next();
}
} else {
if (iterator->OutOfRange(iterator->target)) {
if (iterator->reverse) {
dbIterator->SeekToLast();
} else {
dbIterator->SeekToFirst();
dbIterator->Prev();
} else {
dbIterator->SeekToLast();
dbIterator->Next();
}
}
else {
if (dbIterator->Valid()) {
int cmp = dbIterator->key().compare(*key);
int cmp = dbIterator->key().compare(*iterator->target);
if (cmp > 0 && iterator->reverse) {
dbIterator->SeekToFirst();
dbIterator->Prev();
} else if (cmp < 0 && !iterator->reverse) {
dbIterator->SeekToLast();
dbIterator->Next();
}
} else {
if (iterator->reverse) {
dbIterator->SeekToLast();
} else {
dbIterator->SeekToFirst();
}
if (dbIterator->Valid()) {
int cmp = dbIterator->key().compare(*iterator->target);
if (cmp > 0 && iterator->reverse) {
dbIterator->SeekToFirst();
dbIterator->Prev();
} else if (cmp < 0 && !iterator->reverse) {
dbIterator->SeekToLast();
dbIterator->Next();
}
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/iterator.h
Expand Up @@ -53,13 +53,15 @@ class Iterator : public Nan::ObjectWrap {
leveldb::Status IteratorStatus ();
void IteratorEnd ();
void Release ();
void ReleaseTarget ();

private:
Database* database;
uint32_t id;
leveldb::Iterator* dbIterator;
leveldb::ReadOptions* options;
leveldb::Slice* start;
leveldb::Slice* target;
std::string* end;
bool seeking;
bool reverse;
Expand All @@ -83,6 +85,7 @@ class Iterator : public Nan::ObjectWrap {
private:
bool Read (std::string& key, std::string& value);
bool GetIterator ();
bool OutOfRange (leveldb::Slice* target);

static NAN_METHOD(New);
static NAN_METHOD(Seek);
Expand Down

0 comments on commit 62aa908

Please sign in to comment.