diff --git a/db/c.cc b/db/c.cc index ee8a472..366dd2d 100644 --- a/db/c.cc +++ b/db/c.cc @@ -15,7 +15,26 @@ #include "leveldb/status.h" #include "leveldb/write_batch.h" -namespace leveldb { +using leveldb::Cache; +using leveldb::Comparator; +using leveldb::CompressionType; +using leveldb::DB; +using leveldb::Env; +using leveldb::FileLock; +using leveldb::Iterator; +using leveldb::Logger; +using leveldb::NewLRUCache; +using leveldb::Options; +using leveldb::RandomAccessFile; +using leveldb::Range; +using leveldb::ReadOptions; +using leveldb::SequentialFile; +using leveldb::Slice; +using leveldb::Snapshot; +using leveldb::Status; +using leveldb::WritableFile; +using leveldb::WriteBatch; +using leveldb::WriteOptions; extern "C" { @@ -172,7 +191,7 @@ void leveldb_release_snapshot( delete snapshot; } -const char* leveldb_property_value( +char* leveldb_property_value( leveldb_t* db, const char* propname) { std::string tmp; @@ -449,5 +468,3 @@ void leveldb_env_destroy(leveldb_env_t* env) { } } // end extern "C" - -} diff --git a/db/db_iter.cc b/db/db_iter.cc index 0be18ff..8849f92 100644 --- a/db/db_iter.cc +++ b/db/db_iter.cc @@ -216,7 +216,6 @@ void DBIter::FindPrevUserEntry() { ValueType value_type = kTypeDeletion; if (iter_->Valid()) { - SaveKey(ExtractUserKey(iter_->key()), &saved_key_); do { ParsedInternalKey ikey; if (ParseKey(&ikey) && ikey.sequence <= sequence_) { @@ -227,6 +226,7 @@ void DBIter::FindPrevUserEntry() { } value_type = ikey.type; if (value_type == kTypeDeletion) { + saved_key_.clear(); ClearSavedValue(); } else { Slice raw_value = iter_->value(); @@ -234,6 +234,7 @@ void DBIter::FindPrevUserEntry() { std::string empty; swap(empty, saved_value_); } + SaveKey(ExtractUserKey(iter_->key()), &saved_key_); saved_value_.assign(raw_value.data(), raw_value.size()); } } diff --git a/db/db_test.cc b/db/db_test.cc index 22fa70c..14eb44d 100644 --- a/db/db_test.cc +++ b/db/db_test.cc @@ -519,6 +519,21 @@ TEST(DBTest, IterSmallAndLargeMix) { delete iter; } +TEST(DBTest, IterMultiWithDelete) { + ASSERT_OK(Put("a", "va")); + ASSERT_OK(Put("b", "vb")); + ASSERT_OK(Put("c", "vc")); + ASSERT_OK(Delete("b")); + ASSERT_EQ("NOT_FOUND", Get("b")); + + Iterator* iter = db_->NewIterator(ReadOptions()); + iter->Seek("c"); + ASSERT_EQ(IterStatus(iter), "c->vc"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "a->va"); + delete iter; +} + TEST(DBTest, Recover) { ASSERT_OK(Put("foo", "v1")); ASSERT_OK(Put("baz", "v5")); diff --git a/doc/index.html b/doc/index.html index 58442e8..8d03c45 100644 --- a/doc/index.html +++ b/doc/index.html @@ -23,7 +23,7 @@ creating it if necessary:
#include <assert> - #include "leveldb/include/db.h" + #include "leveldb/db.h" leveldb::DB* db; leveldb::Options options; @@ -78,7 +78,7 @@ Such problems can be avoided by using theWriteBatch
class to atomically apply a set of updates:
- #include "leveldb/include/write_batch.h" + #include "leveldb/write_batch.h" ... std::string value; leveldb::Status s = db->Get(leveldb::ReadOptions(), key1, &value); @@ -296,7 +296,7 @@ subclass ofleveldb::Comparator
that expresses these rules: } // Ignore the following methods for now: - const char* Name() { return "TwoPartComparator"; } + const char* Name() const { return "TwoPartComparator"; } void FindShortestSeparator(std::string*, const leveldb::Slice&) const { } void FindShortSuccessor(std::string*) const { } }; @@ -333,7 +333,7 @@ version numbers found in the keys to decide how to interpret them.Performance
Performance can be tuned by changing the default values of the -types defined in
leveldb/include/options.h
. +types defined ininclude/leveldb/options.h
.
Block size
@@ -371,7 +371,7 @@ filesystem and each file stores a sequence of compressed blocks. If uncompressed block contents.
- #include "leveldb/include/cache.h" + #include "leveldb/cache.h" leveldb::Options options; options.cache = leveldb::NewLRUCache(100 * 1048576); // 100MB cache diff --git a/util/testharness.cc b/util/testharness.cc index b686ac3..6f42700 100644 --- a/util/testharness.cc +++ b/util/testharness.cc @@ -4,6 +4,8 @@ #include "util/testharness.h" +#include+#include #include #include @@ -32,10 +34,20 @@ bool RegisterTest(const char* base, const char* name, void (*func)()) { } int RunAllTests() { + const char* matcher = getenv("LEVELDB_TESTS"); + int num = 0; if (tests != NULL) { for (int i = 0; i < tests->size(); i++) { const Test& t = (*tests)[i]; + if (matcher != NULL) { + std::string name = t.base; + name.push_back('.'); + name.append(t.name); + if (strstr(name.c_str(), matcher) == NULL) { + continue; + } + } fprintf(stderr, "==== Test %s.%s\n", t.base, t.name); (*t.func)(); ++num; diff --git a/util/testharness.h b/util/testharness.h index 13ab914..6f1a9c3 100644 --- a/util/testharness.h +++ b/util/testharness.h @@ -15,7 +15,16 @@ namespace leveldb { namespace test { -// Run all tests registered by the TEST() macro. +// Run some of the tests registered by the TEST() macro. If the +// environment variable "LEVELDB_TESTS" is not set, runs all tests. +// Otherwise, runs only the tests whose name contains the value of +// "LEVELDB_TESTS" as a substring. E.g., suppose the tests are: +// TEST(Foo, Hello) { ... } +// TEST(Foo, World) { ... } +// LEVELDB_TESTS=Hello will run the first test +// LEVELDB_TESTS=o will run both tests +// LEVELDB_TESTS=Junk will run no tests +// // Returns 0 if all tests pass. // Dies or returns a non-zero value if some test fails. extern int RunAllTests();