diff --git a/Makefile b/Makefile index 18386f2..8385d44 100644 --- a/Makefile +++ b/Makefile @@ -8,9 +8,9 @@ CC = g++ # Uncomment exactly one of the lines labelled (A), (B), and (C) below # to switch between compilation modes. -OPT = -O2 -DNDEBUG # (A) Production use (optimized mode) -# OPT = -g2 # (B) Debug mode, w/ full line-level debugging symbols -# OPT = -O2 -g2 -DNDEBUG # (C) Profiling mode: opt, but w/debugging symbols +OPT ?= -O2 -DNDEBUG # (A) Production use (optimized mode) +# OPT ?= -g2 # (B) Debug mode, w/ full line-level debugging symbols +# OPT ?= -O2 -g2 -DNDEBUG # (C) Profiling mode: opt, but w/debugging symbols #----------------------------------------------- # detect what platform we're building on @@ -38,7 +38,7 @@ endif CFLAGS = -c -I. -I./include $(PORT_CFLAGS) $(PLATFORM_CFLAGS) $(OPT) $(SNAPPY_CFLAGS) -LDFLAGS=$(PLATFORM_LDFLAGS) $(SNAPPY_LDFLAGS) $(GOOGLE_PERFTOOLS_LDFLAGS) +LDFLAGS += $(PLATFORM_LDFLAGS) $(SNAPPY_LDFLAGS) $(GOOGLE_PERFTOOLS_LDFLAGS) LIBOBJECTS = \ ./db/builder.o \ diff --git a/db/db_test.cc b/db/db_test.cc index f1cb949..5dc3b02 100644 --- a/db/db_test.cc +++ b/db/db_test.cc @@ -1146,26 +1146,50 @@ TEST(DBTest, CustomComparator) { public: virtual const char* Name() const { return "test.NumberComparator"; } virtual int Compare(const Slice& a, const Slice& b) const { - return (strtol(a.ToString().c_str(), NULL, 0) - - strtol(b.ToString().c_str(), NULL, 0)); + return ToNumber(a) - ToNumber(b); + } + virtual void FindShortestSeparator(std::string* s, const Slice& l) const { + ToNumber(*s); // Check format + ToNumber(l); // Check format + } + virtual void FindShortSuccessor(std::string* key) const { + ToNumber(*key); // Check format + } + private: + static int ToNumber(const Slice& x) { + // Check that there are no extra characters. + ASSERT_TRUE(x.size() >= 2 && x[0] == '[' && x[x.size()-1] == ']') + << EscapeString(x); + int val; + char ignored; + ASSERT_TRUE(sscanf(x.ToString().c_str(), "[%i]%c", &val, &ignored) == 1) + << EscapeString(x); + return val; } - virtual void FindShortestSeparator(std::string* s, const Slice& l) const {} - virtual void FindShortSuccessor(std::string* key) const {} }; NumberComparator cmp; Options new_options; new_options.create_if_missing = true; new_options.comparator = &cmp; + new_options.write_buffer_size = 1000; // Compact more often DestroyAndReopen(&new_options); - ASSERT_OK(Put("10", "ten")); - ASSERT_OK(Put("0x14", "twenty")); + ASSERT_OK(Put("[10]", "ten")); + ASSERT_OK(Put("[0x14]", "twenty")); for (int i = 0; i < 2; i++) { - ASSERT_EQ("ten", Get("10")); - ASSERT_EQ("ten", Get("0xa")); - ASSERT_EQ("twenty", Get("20")); - ASSERT_EQ("twenty", Get("0x14")); - Compact("0", "9999"); - fprintf(stderr, "ss\n%s\n", DumpSSTableList().c_str()); + ASSERT_EQ("ten", Get("[10]")); + ASSERT_EQ("ten", Get("[0xa]")); + ASSERT_EQ("twenty", Get("[20]")); + ASSERT_EQ("twenty", Get("[0x14]")); + Compact("[0]", "[9999]"); + } + + for (int run = 0; run < 2; run++) { + for (int i = 0; i < 1000; i++) { + char buf[100]; + snprintf(buf, sizeof(buf), "[%d]", i*10); + ASSERT_OK(Put(buf, buf)); + } + Compact("[0]", "[1000000]"); } } diff --git a/db/dbformat.cc b/db/dbformat.cc index 4594a57..9168f99 100644 --- a/db/dbformat.cc +++ b/db/dbformat.cc @@ -73,9 +73,10 @@ void InternalKeyComparator::FindShortestSeparator( Slice user_limit = ExtractUserKey(limit); std::string tmp(user_start.data(), user_start.size()); user_comparator_->FindShortestSeparator(&tmp, user_limit); - if (user_comparator_->Compare(*start, tmp) < 0) { - // User key has become larger. Tack on the earliest possible - // number to the shortened user key. + if (tmp.size() < user_start.size() && + user_comparator_->Compare(user_start, tmp) < 0) { + // User key has become shorter physically, but larger logically. + // Tack on the earliest possible number to the shortened user key. PutFixed64(&tmp, PackSequenceAndType(kMaxSequenceNumber,kValueTypeForSeek)); assert(this->Compare(*start, tmp) < 0); assert(this->Compare(tmp, limit) < 0); @@ -87,9 +88,10 @@ void InternalKeyComparator::FindShortSuccessor(std::string* key) const { Slice user_key = ExtractUserKey(*key); std::string tmp(user_key.data(), user_key.size()); user_comparator_->FindShortSuccessor(&tmp); - if (user_comparator_->Compare(user_key, tmp) < 0) { - // User key has become larger. Tack on the earliest possible - // number to the shortened user key. + if (tmp.size() < user_key.size() && + user_comparator_->Compare(user_key, tmp) < 0) { + // User key has become shorter physically, but larger logically. + // Tack on the earliest possible number to the shortened user key. PutFixed64(&tmp, PackSequenceAndType(kMaxSequenceNumber,kValueTypeForSeek)); assert(this->Compare(*key, tmp) < 0); key->swap(tmp); diff --git a/util/comparator.cc b/util/comparator.cc index cfb49ce..eed9d2f 100644 --- a/util/comparator.cc +++ b/util/comparator.cc @@ -64,10 +64,13 @@ class BytewiseComparatorImpl : public Comparator { } }; } // namespace -static const BytewiseComparatorImpl bytewise; + +// Intentionally not destroyed to prevent destructor racing +// with background threads. +static const Comparator* bytewise = new BytewiseComparatorImpl; const Comparator* BytewiseComparator() { - return &bytewise; + return bytewise; } } // namespace leveldb