Wouter Bolsterlee | 17 Jun 2013 22:51
Picon
Picon
Favicon
Gravatar

[announce] Plyvel 0.4, a fast and feature-rich Python interface to LevelDB

Hi all,

I'm happy to announce the release of Plyvel 0.4. This release adds
support for an optional 'default' argument to all .get() methods.

Plyvel is a fast and feature-rich Python interface to LevelDB. Plyvel's
key features are:

* Rich feature set
* Friendly Pythonic API
* High performance
* Extensive documentation
* Python 2 and Python 3 compatibility

More information:

* Online documentation: https://plyvel.readthedocs.org/
* Project page: https://github.com/wbolster/plyvel
* Python Package Index (PyPI): https://pypi.python.org/pypi/plyvel/

Cheers,

    — Wouter

--

-- 
You received this message because you are subscribed to the Google Groups "leveldb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to leveldb+unsubscribe <at> googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

(Continue reading)

donzell.wu | 17 Jun 2013 16:53
Picon

rename is not durable,may cause db corrupt?

rename(tmpfile,CURRENT) is atomic but not durable,if OS crash when leveldb has done DeleteObsoleteFiles(),seems like that db may corrupt. Old manifest has been deleted by DeleteObsoleteFiles() but old CURRENT file may stay unchanged ,pointing to old manifest ,since rename is not durable.
If it is true,seems that fsync on the directory is needed?
see http://stackoverflow.com/questions/3764822/how-to-durably-rename-a-file-in-posix

--
You received this message because you are subscribed to the Google Groups "leveldb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to leveldb+unsubscribe <at> googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 
leveldb | 15 Jun 2013 07:28

Issue 179 in leveldb: My implementation: Compaction IO speed limitation

Status: New
Owner: ----
Labels: Type-Defect Priority-Medium

New issue 179 by wuzuy... <at> gmail.com: My implementation: Compaction IO speed  
limitation
http://code.google.com/p/leveldb/issues/detail?id=179

Hi, everyone:

I created an issue days  
ago(https://code.google.com/p/leveldb/issues/detail?id=168&sort=-id), to  
require the feature of compaction IO speed limitaion. But no reponse.

As we know, the leveldb has extremly BAD performance during compaction,  
because it eats up all the disk IO capacity. So a compaction IO speed  
limitation feature is very important.

I wrote my own. Here is some of the codes:

diff --git a/deps/leveldb-1.9.0/db/db_impl.cc  
b/deps/leveldb-1.9.0/db/db_impl.cc
index c9de169..56915f4 100644
--- a/deps/leveldb-1.9.0/db/db_impl.cc
+++ b/deps/leveldb-1.9.0/db/db_impl.cc
 <at>  <at>  -805,6 +805,22  <at>  <at>  Status  
DBImpl::FinishCompactionOutputFile(CompactionState* compact,
            (unsigned long long) output_number,
            (unsigned long long) current_entries,
            (unsigned long long) current_bytes);
+
+               // Writing current_bytes to disk is considered no  
expense(cost no time),
+               // so we calculate how many IOs will match the compaction  
speed,
+               // then sleep 1s/IOs
+               // Added by me <at> ideawu.com
+               int mbs = current_bytes/1024/1024;
+               if(options_.compaction_speed > 0 && mbs > 1){
+                       int count = options_.compaction_speed/mbs;
+                       if(count < 1){
+                               count = 1;
+                       }
+                       int pause = 1000 * 1000 / count;
+                       Log(options_.info_log, "compaction_speed: %d MB,  
pause: %d us",
+                               options_.compaction_speed, pause);
+                       env_->SleepForMicroseconds(pause);
+               }
      }
    }
    return s;

This is a very primative approach, I am expecting there is an official  
implementation.

The full codes is here:  
https://github.com/ideawu/ssdb/tree/master/deps/leveldb-1.9.0

-- 
You received this message because this project is configured to send all  
issue notifications to this address.
You may adjust your notification preferences at:
https://code.google.com/hosting/settings

--

-- 
You received this message because you are subscribed to the Google Groups "leveldb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to leveldb+unsubscribe <at> googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Kevin Regan | 15 Jun 2013 01:05
Picon

Question about database compaction and snapshots

Currently, I'm doing a CompactRange(start_key, end_key) whenever I delete a range of keys in the database.  This is to work around the issue of the database slowing down after a large delete (until it is compacted).

My question is, if I've got an active snapshot on the range that I delete and compact (created before I start the delete and still in existence after the compact), will the data actually be compacted?

I haven't noticed any issues -- I was just curious.

Thanks,
Kevin

--
You received this message because you are subscribed to the Google Groups "leveldb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to leveldb+unsubscribe <at> googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 
Joao Eduardo Luis | 14 Jun 2013 02:21

tcmalloc segfault from leveldb::Version::AddIterators

Dear list,

Has anyone heard of any issues with leveldb and tcmalloc?  We've hit a 
similar issue to the one bellow, on Ceph, a while back, due to a double 
delete resulting from lack of proper locking, but this one coming from 
leveldb was a first for us.

Bellow [3] is the stack trace as dumped at the time of the segfault. 
Hoping this might shed light to what's happening, let me explain what 
happened just before we hit leveldb prior to the segfault.

While a value from leveldb via our own abstraction (LevelDBStore) class, 
our 'get' function [1] receives a 'prefix' and a set of 'suffixes' whose 
values should be returned on yet another map.  Long story short, we 
create an iterator to walk over all keys starting with said prefix and 
fill the map with any keys matching the provided suffixes.

However, in this case, we never got to walk over the iterator, as 
leveldb went boom as while creating said iterator (which in turn is 
returned by [2]).

leveldb version would be 0+20120125.git3c8be10-1 from ubuntu 12.04.

Let me know if there's any other info you might need to shed better 
light on what's happening.

Cheers!

   -Joao

[1]:

int LevelDBStore::get(
     const string &prefix,
     const std::set<string> &keys,
     std::map<string, bufferlist> *out)
{
   KeyValueDB::Iterator it = get_iterator(prefix);
   for (std::set<string>::const_iterator i = keys.begin();
        i != keys.end();
        ++i) {
     it->lower_bound(*i);
     if (it->valid() && it->key() == *i) {
       out->insert(make_pair(*i, it->value()));
     } else if (!it->valid())
       break;
   }
   logger->inc(l_leveldb_gets);
   return 0;
}

[2]:

WholeSpaceIterator _get_iterator() {
   return std::tr1::shared_ptr<KeyValueDB::WholeSpaceIteratorImpl>(
     new LevelDBWholeSpaceIteratorImpl(
       db->NewIterator(leveldb::ReadOptions())
     )
   );

[3]:

ceph version 0.61.3 (92b1e398576d55df8e5888dd1a9545ed3fd99532)
1: /usr/bin/ceph-mon() [0x5a08b2]
2: (()+0xf030) [0x7f09ce2dd030]
3: 
(tcmalloc::ThreadCache::ReleaseToCentralCache(tcmalloc::ThreadCache::FreeList*, 
unsigned long, int)+0xeb) [0x7f09cd6f9c3b]
4: (tcmalloc::ThreadCache::ListTooLong(tcmalloc::ThreadCache::FreeList*, 
unsigned long)+0x23) [0x7f09cd6f9cc3]
5: (operator delete(void*)+0x2db) [0x7f09cd70b2bb]
6: (std::vector<leveldb::Iterator*, std::allocator<leveldb::Iterator*> 
 >::_M_insert_aux(__gnu_cxx::__normal_iterator<leveldb::Iterator**, 
std::vector<leveldb::Iterator*, std::allocator<leveldb::Iterator*> > >, 
leveldb::Iterator* const&)+0x15b) [0x7f09cd4a21eb]
7: (leveldb::Version::AddIterators(leveldb::ReadOptions const&, 
std::vector<leveldb::Iterator*, std::allocator<leveldb::Iterator*> 
 >*)+0x12d) [0x7f09cd4aea0d]
8: (leveldb::DBImpl::NewInternalIterator(leveldb::ReadOptions const&, 
unsigned long*)+0x10f) [0x7f09cd49cc5f]
9: (leveldb::DBImpl::NewIterator(leveldb::ReadOptions const&)+0x14) 
[0x7f09cd49cd94]
10: (LevelDBStore::_get_iterator()+0x41) [0x58dc31]
11: (LevelDBStore::get(std::string const&, std::set<std::string, 
std::less<std::string>, std::allocator<std::string> > const&, 
std::map<std::string, ceph::buffer::list, std::less<std::string>, 
std::allocator<std::pair<std::string const, ceph::buffer::list> > 
 >*)+0x32) [0x58cca2]
  12: (MonitorDBStore::get(std::string const&, std::string const&, 
ceph::buffer::list&)+0xbd) [0x4a9bcd]

-- 
Joao Eduardo Luis
Software Engineer | http://inktank.com | http://ceph.com

--

-- 
You received this message because you are subscribed to the Google Groups "leveldb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to leveldb+unsubscribe <at> googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

David Grogan | 14 Jun 2013 01:28

LevelDB 1.11.0 released

Fixes issues

As well as the issue reported by edouarda14 <at> gmail.com about MissingSSTFile unit test failing on windows.

--
You received this message because you are subscribed to the Google Groups "leveldb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to leveldb+unsubscribe <at> googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 
leveldb | 13 Jun 2013 03:12

Issue 178 in leveldb: Compaction causes previously deleted value to reappear

Status: New
Owner: ----
Labels: Type-Defect Priority-Medium

New issue 178 by kevin.d.... <at> gmail.com: Compaction causes previously  
deleted value to reappear
http://code.google.com/p/leveldb/issues/detail?id=178

What steps will reproduce the problem?
1. Compile and run the included test program.
2. Note that not all value have been properly deleted.
3. Recompile the test program with the CompactRange call commented out.
4. Note that all values have been properly deleted.

What is the expected output? What do you see instead?

The expected output from the program is:

Creating first key range
Creating second key range
Deleting second key range
Compacting database
Counting number of keys left
Found 0 keys

The actual output is:

Creating first key range
Creating second key range
Deleting second key range
Compacting database
Counting number of keys left
Found 1222706 keys

What version of the product are you using? On what operating system?

1.9, 1.10
FreeBSD, Ubuntu 12.10

Please provide any additional information below.

#include <iostream>
#include <sstream>
#include <cstdlib>

#include <leveldb/db.h>
#include <leveldb/write_batch.h>

namespace {

const std::string DB_PATH = "/tmp/my_test_db";
size_t NUM_KEYS = 1100000;

void
check_status(const leveldb::Status& status, const std::string& error_msg)
{
	if (!status.ok()) {
		std::cerr << "ERROR: " << error_msg << ": " <<
		    status.ToString() << std::endl;
		std::exit(1);
	}
}

std::string
create_key_1(size_t i)
{
	std::ostringstream out;
	out << "my_key_" << i;
	return out.str();
}

std::string
create_key_2(size_t i)
{
	return create_key_1(i) + "_xxx";
}

} // namespace

int
main (int argc, char** argv)
{
	// open database
	leveldb::DB* db;
	leveldb::Options db_options;
	db_options.create_if_missing = true;
	leveldb::Status status = leveldb::DB::Open(db_options, DB_PATH, &db);
	check_status(status, "Could not open database");

	// create first key range
	std::cout << "Creating first key range" << std::endl;
	leveldb::WriteBatch batch;
	for (size_t i = 0; i < NUM_KEYS; i++) {
		batch.Put(create_key_1(i), "value for range 1 key");
	}
	status = db->Write(leveldb::WriteOptions(), &batch);
	check_status(status, "Could not create keys for first range");

	// create second key range
	std::cout << "Creating second key range" << std::endl;
	batch.Clear();
	for (size_t i = 0; i < NUM_KEYS; i++) {
		batch.Put(create_key_2(i), "value for range 2 key");
	}
	status = db->Write(leveldb::WriteOptions(), &batch);
	check_status(status, "Could not create keys for second range");

	// delete second key range
	std::cout << "Deleting second key range" << std::endl;
	batch.Clear();
	for (size_t i = 0; i < NUM_KEYS; i++) {
		batch.Delete(create_key_2(i));
	}
	status = db->Write(leveldb::WriteOptions(), &batch);
	check_status(status, "Could not delete keys");

	// compact database
	std::cout << "Compacting database" << std::endl;
	db->CompactRange(NULL, NULL);

	// count the keys
	std::cout << "Counting number of keys left" << std::endl;
	leveldb::Iterator* iter = db->NewIterator(leveldb::ReadOptions());;
	size_t num_keys = 0;
	for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
		num_keys++;
	}
	delete iter;
	std::cout << "Found " << num_keys << " keys" << std::endl;

	// close database
	delete db;
}

Attachments:
	compact_test.cpp  2.2 KB

-- 
You received this message because this project is configured to send all  
issue notifications to this address.
You may adjust your notification preferences at:
https://code.google.com/hosting/settings

--

-- 
You received this message because you are subscribed to the Google Groups "leveldb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to leveldb+unsubscribe <at> googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Kevin Regan | 12 Jun 2013 23:45
Picon

Compaction causes previous deleted values to reappear


I was noticing an issue with database compaction causing some values that had been deleted to mysteriously reappear.  I've included an example below.

The example creates two (interspersed) ranges of keys and then deletes the second one.  When the compaction is done, some of the deleted keys are still seen in the database.  When the compaction line is commented out, the example works correctly.

This seems to be related to the size of the database (keys + values), with the bug only showing up after a large number of keys is used.  Also, I'm only seeing the problem when doing batch deletes.


Sincerely,
Kevin Regan


#include <iostream>
#include <sstream>
#include <cstdlib>

#include <leveldb/db.h>
#include <leveldb/write_batch.h>


namespace {

const std::string DB_PATH = "/tmp/my_test_db";
size_t NUM_KEYS = 1100000;

void
check_status(const leveldb::Status& status, const std::string& error_msg)
{
    if (!status.ok()) {
        std::cerr << "ERROR: " << error_msg << ": " <<
            status.ToString() << std::endl;
        std::exit(1);
    }
}

std::string
create_key_1(size_t i)
{
    std::ostringstream out;
    out << "my_key_" << i;
    return out.str();
}

std::string
create_key_2(size_t i)
{
    return create_key_1(i) + "_xxx";
}

} // namespace

int
main (int argc, char** argv)
{
    // open database
    leveldb::DB* db;
    leveldb::Options db_options;
    db_options.create_if_missing = true;
    leveldb::Status status = leveldb::DB::Open(db_options, DB_PATH, &db);
    check_status(status, "Could not open database");

    // create first key range
    std::cout << "Creating first key range" << std::endl;
    leveldb::WriteBatch batch;
    for (size_t i = 0; i < NUM_KEYS; i++) {
        batch.Put(create_key_1(i), "value for range 1 key");
    }
    status = db->Write(leveldb::WriteOptions(), &batch);
    check_status(status, "Could not create keys for first range");

    // create second key range
    std::cout << "Creating second key range" << std::endl;
    batch.Clear();
    for (size_t i = 0; i < NUM_KEYS; i++) {
        batch.Put(create_key_2(i), "value for range 2 key");
    }
    status = db->Write(leveldb::WriteOptions(), &batch);
    check_status(status, "Could not create keys for second range");

    // delete second key range
    std::cout << "Deleting second key range" << std::endl;
    batch.Clear();
    for (size_t i = 0; i < NUM_KEYS; i++) {
        batch.Delete(create_key_2(i));
    }
    status = db->Write(leveldb::WriteOptions(), &batch);
    check_status(status, "Could not delete keys");

    // compact database
    std::cout << "Compacting database" << std::endl;
    std::string start_key = create_key_1(0);
    std::string end_key = create_key_1(NUM_KEYS - 1);
    leveldb::Slice least(start_key.data(), start_key.size());
    leveldb::Slice greatest(end_key.data(), end_key.size());
   
    // commenting out the line below causes the example to work correctly
    db->CompactRange(&least, &greatest);

    // count the keys
    std::cout << "Counting number of keys left" << std::endl;
    leveldb::Iterator* iter = db->NewIterator(leveldb::ReadOptions());;
    size_t num_keys = 0;
    for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
        num_keys++;
    }
    delete iter;
    std::cout << "Found " << num_keys << " keys" << std::endl;

    // close database
    delete db;
}

--
You received this message because you are subscribed to the Google Groups "leveldb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to leveldb+unsubscribe <at> googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 
leveldb | 11 Jun 2013 08:08

Issue 177 in leveldb: Patch for /Makefile failing PLATFORM=IOS with XCode 4.6

Status: New
Owner: ----
Labels: Type-Patch

New issue 177 by dentaroo <at> gmail.com: Patch for /Makefile failing  
PLATFORM=IOS with XCode 4.6
http://code.google.com/p/leveldb/issues/detail?id=177

Fix failure to make for iOS due to the compilers not being in the directory  
under the iOS platforms for XCode 4.6
"
make: 

/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/c++:

No such file or directory
make: *** [db/builder.o] Error 1
"

Attachments:
	Makefile.patch  1.0 KB

-- 
You received this message because this project is configured to send all  
issue notifications to this address.
You may adjust your notification preferences at:
https://code.google.com/hosting/settings

--

-- 
You received this message because you are subscribed to the Google Groups "leveldb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to leveldb+unsubscribe <at> googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

leveldb | 10 Jun 2013 22:03

Issue 176 in leveldb: Concurrency support for multiple processes (1 exclusive initializer / n readers)

Status: New
Owner: ----
Labels: Type-Defect Priority-Medium

New issue 176 by shri... <at> gmail.com: Concurrency support for multiple  
processes (1 exclusive initializer / n readers)
http://code.google.com/p/leveldb/issues/detail?id=176

Can the designers of leveldb explain the rational behind the design  
decision of not supporting multiple processes in leveldb implementation?

The documentation clearly says, under Concurrency section that: "A database  
may only be opened by one process at a time. The leveldb implementation  
acquires a lock from the operating system to prevent misuse."

Currently I can see that when one process opens level db, it uses fcntl  
with RW lock (exclusive lock). However this is a severely limiting, as no  
other process can ever open the same database even if it wants to just  
inspect the database contents for RDONLY purposes.

The use case for example is - one process exclusively opens leveldb  
database and fills up the database, then closes it. Then n different  
processes start reading that database.

-- 
You received this message because this project is configured to send all  
issue notifications to this address.
You may adjust your notification preferences at:
https://code.google.com/hosting/settings

--

-- 
You received this message because you are subscribed to the Google Groups "leveldb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to leveldb+unsubscribe <at> googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Ugorji Nwoke | 10 Jun 2013 17:14
Picon

Does BloomFilter provide benefits when using iterators?

I wrap leveldb in a server accessed over the network.

In some scenarios (e.g. when values in leveldb may be large), I handle a multi-get request by sorting the keys, creating an iterator and seeking to each key and grabbing the value. I do this to workaround the un-necessary copy which Get does (where it copies bytes into a std::string).

In using an iterator in this fashion, does a BloomFilter provide any benefits? Or does BloomFilter only provide benefits for direct Get calls?


--
You received this message because you are subscribed to the Google Groups "leveldb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to leveldb+unsubscribe <at> googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Gmane