Question

Suppose you don't know the exact keys in a leveldb database.

I tried inserting 3 keys and using GetApproximateSizes on the key range, the result is consistently zero.

So how do you check if there are any keys in leveldb ?

Was it helpful?

Solution 2

Can't you just use leveldb scan and print all the keys and values. For example to print all keys and values in the database you can do the following :

  leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions());
  for (it->SeekToFirst(); it->Valid(); it->Next()) {
    cout << it->key().ToString() << ": "  << it->value().ToString() << endl;
  }
  assert(it->status().ok());  // Check for any errors found during the scan
  delete it;

Now GetApproximateSizes give zero value because you have just inserted 3 keys and they are still in memory (memtable) and has not reached the filesystem yet. Once the memtable is full (by default 4MB) then it creates the first file in level 0. So it is more useful on a bigger database and a larger key range.

In your case the only place in filesystem the data is present would the redo log and if your keys are strings you could do a quick check by calling 'strings logfile' (in linux) in the db directory to print out the strings part of your keys as a quick way to confirm that data has gone in.

OTHER TIPS

We are using leveldb in a NodeJS project via the higher-level API levelUP. Using the levelUP API, you can ask for a stream of all keys and set limit=1 to limit the response to at most one key. If the database is empty, you will get an empty stream, otherwise you'll get a stream with exactly one item.

var empty = true;
db.createReadStream(db, {
    keys: true,
    values: false,
    limit: 1
}.on('data', function(data) {
    empty = false;
}.on('end', function() {
    console.log('db is ' + (empty ? 'empty' : 'not empty')); 
});

We use this technique in the npm module level-is-empty.

Since you need a solution using leveldb's native API, I looked into how levelUP is implementing the createReadStream() API.

In levelUP, createReadStream is implemented using an iterator.

In levelDOWN, the native Iterator instance is created here. Calling next on it tells you whether the iterator has more data or is finished.

I found an example of how to use native leveldb iterators here

Apparently, the iterator method Valid() tells you whether there are more keys to read. So by simply calling SeekToFirst(), followed by Valid(), you should be able to find out if there is any key in the db at all.

Here's my best guess (the code is untested, I don't have a C compiler at hand)

leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions());
it->SeekToFirst();
bool isEmpty = !(it->Valid());
delete it;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top