From 260c29762a913fb7a1bbe061e65e89334f6fd084 Mon Sep 17 00:00:00 2001 From: Peter Mattis Date: Wed, 6 Jan 2016 14:46:32 -0500 Subject: [PATCH] Fix index seeking in BlockTableReader::PrefixMayMatch. PrefixMayMatch previously seeked in the prefix index using an internal key with a sequence number of 0. This would cause the prefix index seek to fall off the end if the last key in the index had a user-key greater than or equal to the key being looked for. Falling off the end of the index in turn results in PrefixMayMatch returning false if the index is in memory. --- table/block_based_table_reader.cc | 2 +- table/table_test.cc | 34 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/table/block_based_table_reader.cc b/table/block_based_table_reader.cc index 023e5c83e..4a358d361 100644 --- a/table/block_based_table_reader.cc +++ b/table/block_based_table_reader.cc @@ -1122,7 +1122,7 @@ bool BlockBasedTable::PrefixMayMatch(const Slice& internal_key) { assert(rep_->ioptions.prefix_extractor != nullptr); auto prefix = rep_->ioptions.prefix_extractor->Transform( ExtractUserKey(internal_key)); - InternalKey internal_key_prefix(prefix, 0, kTypeValue); + InternalKey internal_key_prefix(prefix, kMaxSequenceNumber, kTypeValue); auto internal_prefix = internal_key_prefix.Encode(); bool may_match = true; diff --git a/table/table_test.cc b/table/table_test.cc index 38ec8400a..abaf5ee91 100644 --- a/table/table_test.cc +++ b/table/table_test.cc @@ -1242,6 +1242,40 @@ TEST_F(BlockBasedTableTest, TotalOrderSeekOnHashIndex) { } } +TEST_F(BlockBasedTableTest, NoopTransformSeek) { + BlockBasedTableOptions table_options; + table_options.filter_policy.reset(NewBloomFilterPolicy(10)); + + Options options; + options.comparator = BytewiseComparator(); + options.table_factory.reset(new BlockBasedTableFactory(table_options)); + options.prefix_extractor.reset(NewNoopTransform()); + + TableConstructor c(options.comparator); + // To tickle the PrefixMayMatch bug it is important that the + // user-key is a single byte so that the index key exactly matches + // the user-key. + InternalKey key("a", 1, kTypeValue); + c.Add(key.Encode().ToString(), "b"); + std::vector keys; + stl_wrappers::KVMap kvmap; + const ImmutableCFOptions ioptions(options); + c.Finish(options, ioptions, table_options, + InternalKeyComparator(options.comparator), &keys, &kvmap); + + auto* reader = c.GetTableReader(); + for (int i = 0; i < 2; ++i) { + ReadOptions ro; + ro.total_order_seek = (i == 0); + std::unique_ptr iter(reader->NewIterator(ro)); + + iter->Seek(key.Encode()); + ASSERT_OK(iter->status()); + ASSERT_TRUE(iter->Valid()); + ASSERT_EQ("a", ExtractUserKey(iter->key()).ToString()); + } +} + static std::string RandomString(Random* rnd, int len) { std::string r; test::RandomString(rnd, len, &r);