plain_table_db_test.cc 39.9 KB
Newer Older
1
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
S
Siying Dong 已提交
2 3 4
//  This source code is licensed under both the GPLv2 (found in the
//  COPYING file in the root directory) and Apache 2.0 License
//  (found in the LICENSE.Apache file in the root directory).
S
Siying Dong 已提交
5 6 7 8
//
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
9 10 11

#ifndef ROCKSDB_LITE

S
Siying Dong 已提交
12 13 14 15 16 17 18 19
#include <algorithm>
#include <set>

#include "db/db_impl.h"
#include "db/version_set.h"
#include "db/write_batch_internal.h"
#include "rocksdb/cache.h"
#include "rocksdb/compaction_filter.h"
K
kailiu 已提交
20
#include "rocksdb/db.h"
S
Siying Dong 已提交
21
#include "rocksdb/env.h"
K
kailiu 已提交
22 23 24
#include "rocksdb/filter_policy.h"
#include "rocksdb/slice_transform.h"
#include "rocksdb/table.h"
25
#include "table/bloom_block.h"
26
#include "table/meta_blocks.h"
K
kailiu 已提交
27
#include "table/plain_table_factory.h"
28
#include "table/plain_table_key_coding.h"
29
#include "table/plain_table_reader.h"
30 31
#include "table/table_builder.h"
#include "util/filename.h"
S
Siying Dong 已提交
32 33 34
#include "util/hash.h"
#include "util/logging.h"
#include "util/mutexlock.h"
35
#include "util/string_util.h"
S
Siying Dong 已提交
36 37 38 39 40 41 42
#include "util/testharness.h"
#include "util/testutil.h"
#include "utilities/merge_operators.h"

using std::unique_ptr;

namespace rocksdb {
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
class PlainTableKeyDecoderTest : public testing::Test {};

TEST_F(PlainTableKeyDecoderTest, ReadNonMmap) {
  std::string tmp;
  Random rnd(301);
  const uint32_t kLength = 2222;
  Slice contents = test::RandomString(&rnd, kLength, &tmp);
  test::StringSource* string_source =
      new test::StringSource(contents, 0, false);

  unique_ptr<RandomAccessFileReader> file_reader(
      test::GetRandomAccessFileReader(string_source));
  unique_ptr<PlainTableReaderFileInfo> file_info(new PlainTableReaderFileInfo(
      std::move(file_reader), EnvOptions(), kLength));

  {
    PlainTableFileReader reader(file_info.get());

    const uint32_t kReadSize = 77;
    for (uint32_t pos = 0; pos < kLength; pos += kReadSize) {
      uint32_t read_size = std::min(kLength - pos, kReadSize);
      Slice out;
      ASSERT_TRUE(reader.Read(pos, read_size, &out));
      ASSERT_EQ(0, out.compare(tmp.substr(pos, read_size)));
    }

D
Dmitri Smirnov 已提交
69
    ASSERT_LT(uint32_t(string_source->total_reads()), kLength / kReadSize / 2);
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
  }

  std::vector<std::vector<std::pair<uint32_t, uint32_t>>> reads = {
      {{600, 30}, {590, 30}, {600, 20}, {600, 40}},
      {{800, 20}, {100, 20}, {500, 20}, {1500, 20}, {100, 20}, {80, 20}},
      {{1000, 20}, {500, 20}, {1000, 50}},
      {{1000, 20}, {500, 20}, {500, 20}},
      {{1000, 20}, {500, 20}, {200, 20}, {500, 20}},
      {{1000, 20}, {500, 20}, {200, 20}, {1000, 50}},
      {{600, 500}, {610, 20}, {100, 20}},
      {{500, 100}, {490, 100}, {550, 50}},
  };

  std::vector<int> num_file_reads = {2, 6, 2, 2, 4, 3, 2, 2};

  for (size_t i = 0; i < reads.size(); i++) {
    string_source->set_total_reads(0);
    PlainTableFileReader reader(file_info.get());
    for (auto p : reads[i]) {
      Slice out;
      ASSERT_TRUE(reader.Read(p.first, p.second, &out));
      ASSERT_EQ(0, out.compare(tmp.substr(p.first, p.second)));
    }
    ASSERT_EQ(num_file_reads[i], string_source->total_reads());
  }
}
S
Siying Dong 已提交
96

97 98
class PlainTableDBTest : public testing::Test,
                         public testing::WithParamInterface<bool> {
K
Kai Liu 已提交
99 100
 protected:
 private:
S
Siying Dong 已提交
101 102 103 104
  std::string dbname_;
  Env* env_;
  DB* db_;

105
  bool mmap_mode_;
S
Siying Dong 已提交
106 107
  Options last_options_;

K
Kai Liu 已提交
108
 public:
109
  PlainTableDBTest() : env_(Env::Default()) {}
S
Siying Dong 已提交
110 111 112

  ~PlainTableDBTest() {
    delete db_;
113
    EXPECT_OK(DestroyDB(dbname_, Options()));
S
Siying Dong 已提交
114 115
  }

116 117 118 119 120 121 122 123
  void SetUp() override {
    mmap_mode_ = GetParam();
    dbname_ = test::TmpDir() + "/plain_table_db_test";
    EXPECT_OK(DestroyDB(dbname_, Options()));
    db_ = nullptr;
    Reopen();
  }

S
Siying Dong 已提交
124 125 126
  // Return the current option configuration.
  Options CurrentOptions() {
    Options options;
S
Stanislau Hlebik 已提交
127 128 129 130 131 132 133 134 135

    PlainTableOptions plain_table_options;
    plain_table_options.user_key_len = 0;
    plain_table_options.bloom_bits_per_key = 2;
    plain_table_options.hash_table_ratio = 0.8;
    plain_table_options.index_sparseness = 3;
    plain_table_options.huge_page_tlb_size = 0;
    plain_table_options.encoding_type = kPrefix;
    plain_table_options.full_scan_mode = false;
136
    plain_table_options.store_index_in_file = false;
S
Stanislau Hlebik 已提交
137 138

    options.table_factory.reset(NewPlainTableFactory(plain_table_options));
139
    options.memtable_factory.reset(NewHashLinkListRepFactory(4, 0, 3, true));
S
Stanislau Hlebik 已提交
140

141
    options.prefix_extractor.reset(NewFixedPrefixTransform(8));
142
    options.allow_mmap_reads = mmap_mode_;
143
    options.allow_concurrent_memtable_write = false;
S
Siying Dong 已提交
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
    return options;
  }

  DBImpl* dbfull() {
    return reinterpret_cast<DBImpl*>(db_);
  }

  void Reopen(Options* options = nullptr) {
    ASSERT_OK(TryReopen(options));
  }

  void Close() {
    delete db_;
    db_ = nullptr;
  }

  void DestroyAndReopen(Options* options = nullptr) {
    //Destroy using last options
    Destroy(&last_options_);
    ASSERT_OK(TryReopen(options));
  }

  void Destroy(Options* options) {
    delete db_;
    db_ = nullptr;
    ASSERT_OK(DestroyDB(dbname_, *options));
  }

  Status PureReopen(Options* options, DB** db) {
    return DB::Open(*options, dbname_, db);
  }

  Status TryReopen(Options* options = nullptr) {
    delete db_;
    db_ = nullptr;
    Options opts;
    if (options != nullptr) {
      opts = *options;
    } else {
      opts = CurrentOptions();
      opts.create_if_missing = true;
    }
    last_options_ = opts;

    return DB::Open(opts, dbname_, &db_);
  }

  Status Put(const Slice& k, const Slice& v) {
    return db_->Put(WriteOptions(), k, v);
  }

  Status Delete(const std::string& k) {
    return db_->Delete(WriteOptions(), k);
  }

  std::string Get(const std::string& k, const Snapshot* snapshot = nullptr) {
200
    ReadOptions options;
S
Siying Dong 已提交
201 202 203 204 205 206 207 208 209 210 211 212 213 214
    options.snapshot = snapshot;
    std::string result;
    Status s = db_->Get(options, k, &result);
    if (s.IsNotFound()) {
      result = "NOT_FOUND";
    } else if (!s.ok()) {
      result = s.ToString();
    }
    return result;
  }


  int NumTableFilesAtLevel(int level) {
    std::string property;
215 216
    EXPECT_TRUE(db_->GetProperty(
        "rocksdb.num-files-at-level" + NumberToString(level), &property));
S
Siying Dong 已提交
217 218 219 220 221 222
    return atoi(property.c_str());
  }

  // Return spread of files per level
  std::string FilesPerLevel() {
    std::string result;
223
    size_t last_non_zero_offset = 0;
S
Siying Dong 已提交
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
    for (int level = 0; level < db_->NumberLevels(); level++) {
      int f = NumTableFilesAtLevel(level);
      char buf[100];
      snprintf(buf, sizeof(buf), "%s%d", (level ? "," : ""), f);
      result += buf;
      if (f > 0) {
        last_non_zero_offset = result.size();
      }
    }
    result.resize(last_non_zero_offset);
    return result;
  }

  std::string IterStatus(Iterator* iter) {
    std::string result;
    if (iter->Valid()) {
      result = iter->key().ToString() + "->" + iter->value().ToString();
    } else {
      result = "(invalid)";
    }
    return result;
  }
};

248
TEST_P(PlainTableDBTest, Empty) {
K
Kai Liu 已提交
249
  ASSERT_TRUE(dbfull() != nullptr);
S
Siying Dong 已提交
250 251 252
  ASSERT_EQ("NOT_FOUND", Get("0000000000000foo"));
}

253 254
extern const uint64_t kPlainTableMagicNumber;

255 256
class TestPlainTableReader : public PlainTableReader {
 public:
L
Lei Jin 已提交
257
  TestPlainTableReader(const EnvOptions& env_options,
258
                       const InternalKeyComparator& icomparator,
259 260 261
                       EncodingType encoding_type, uint64_t file_size,
                       int bloom_bits_per_key, double hash_table_ratio,
                       size_t index_sparseness,
262
                       const TableProperties* table_properties,
263
                       unique_ptr<RandomAccessFileReader>&& file,
L
Lei Jin 已提交
264
                       const ImmutableCFOptions& ioptions,
265
                       const SliceTransform* prefix_extractor,
266 267 268
                       bool* expect_bloom_not_match, bool store_index_in_file,
                       uint32_t column_family_id,
                       const std::string& column_family_name)
L
Lei Jin 已提交
269
      : PlainTableReader(ioptions, std::move(file), env_options, icomparator,
270 271
                         encoding_type, file_size, table_properties,
                         prefix_extractor),
272
        expect_bloom_not_match_(expect_bloom_not_match) {
273
    Status s = MmapDataIfNeeded();
274
    EXPECT_TRUE(s.ok());
275 276 277 278

    s = PopulateIndex(const_cast<TableProperties*>(table_properties),
                      bloom_bits_per_key, hash_table_ratio, index_sparseness,
                      2 * 1024 * 1024);
279
    EXPECT_TRUE(s.ok());
280 281

    TableProperties* props = const_cast<TableProperties*>(table_properties);
282 283
    EXPECT_EQ(column_family_id, static_cast<uint32_t>(props->column_family_id));
    EXPECT_EQ(column_family_name, props->column_family_name);
284 285 286
    if (store_index_in_file) {
      auto bloom_version_ptr = props->user_collected_properties.find(
          PlainTablePropertyNames::kBloomVersion);
287 288
      EXPECT_TRUE(bloom_version_ptr != props->user_collected_properties.end());
      EXPECT_EQ(bloom_version_ptr->second, std::string("1"));
L
Lei Jin 已提交
289
      if (ioptions.bloom_locality > 0) {
290 291
        auto num_blocks_ptr = props->user_collected_properties.find(
            PlainTablePropertyNames::kNumBloomBlocks);
292
        EXPECT_TRUE(num_blocks_ptr != props->user_collected_properties.end());
293 294
      }
    }
295 296 297 298 299 300 301
  }

  virtual ~TestPlainTableReader() {}

 private:
  virtual bool MatchBloom(uint32_t hash) const override {
    bool ret = PlainTableReader::MatchBloom(hash);
302
    if (*expect_bloom_not_match_) {
303
      EXPECT_TRUE(!ret);
304
    } else {
305
      EXPECT_TRUE(ret);
306
    }
307 308 309 310 311 312 313 314 315
    return ret;
  }
  bool* expect_bloom_not_match_;
};

extern const uint64_t kPlainTableMagicNumber;
class TestPlainTableFactory : public PlainTableFactory {
 public:
  explicit TestPlainTableFactory(bool* expect_bloom_not_match,
316 317 318
                                 const PlainTableOptions& options,
                                 uint32_t column_family_id,
                                 std::string column_family_name)
S
Stanislau Hlebik 已提交
319 320 321 322
      : PlainTableFactory(options),
        bloom_bits_per_key_(options.bloom_bits_per_key),
        hash_table_ratio_(options.hash_table_ratio),
        index_sparseness_(options.index_sparseness),
323
        store_index_in_file_(options.store_index_in_file),
324 325 326
        expect_bloom_not_match_(expect_bloom_not_match),
        column_family_id_(column_family_id),
        column_family_name_(std::move(column_family_name)) {}
327

328 329 330 331
  Status NewTableReader(
      const TableReaderOptions& table_reader_options,
      unique_ptr<RandomAccessFileReader>&& file, uint64_t file_size,
      unique_ptr<TableReader>* table,
A
Andrew Kryczka 已提交
332
      bool /*prefetch_index_and_filter_in_cache*/) const override {
333
    TableProperties* props = nullptr;
334 335
    auto s =
        ReadTableProperties(file.get(), file_size, kPlainTableMagicNumber,
336 337
                            table_reader_options.ioptions, &props,
                            true /* compression_type_missing */);
338
    EXPECT_TRUE(s.ok());
339

340 341 342
    if (store_index_in_file_) {
      BlockHandle bloom_block_handle;
      s = FindMetaBlock(file.get(), file_size, kPlainTableMagicNumber,
343
                        table_reader_options.ioptions,
344 345
                        BloomBlockBuilder::kBloomBlock, &bloom_block_handle,
                        /* compression_type_missing */ true);
346
      EXPECT_TRUE(s.ok());
347 348

      BlockHandle index_block_handle;
349
      s = FindMetaBlock(file.get(), file_size, kPlainTableMagicNumber,
350
                        table_reader_options.ioptions,
351
                        PlainTableIndexBuilder::kPlainTableIndexBlock,
352
                        &index_block_handle, /* compression_type_missing */ true);
353
      EXPECT_TRUE(s.ok());
354 355
    }

356 357 358 359 360 361 362
    auto& user_props = props->user_collected_properties;
    auto encoding_type_prop =
        user_props.find(PlainTablePropertyNames::kEncodingType);
    assert(encoding_type_prop != user_props.end());
    EncodingType encoding_type = static_cast<EncodingType>(
        DecodeFixed32(encoding_type_prop->second.c_str()));

363
    std::unique_ptr<PlainTableReader> new_reader(new TestPlainTableReader(
364 365
        table_reader_options.env_options,
        table_reader_options.internal_comparator, encoding_type, file_size,
366
        bloom_bits_per_key_, hash_table_ratio_, index_sparseness_, props,
367 368
        std::move(file), table_reader_options.ioptions,
        table_reader_options.prefix_extractor, expect_bloom_not_match_,
369
        store_index_in_file_, column_family_id_, column_family_name_));
370 371 372 373 374 375 376 377 378

    *table = std::move(new_reader);
    return s;
  }

 private:
  int bloom_bits_per_key_;
  double hash_table_ratio_;
  size_t index_sparseness_;
379
  bool store_index_in_file_;
380
  bool* expect_bloom_not_match_;
381 382
  const uint32_t column_family_id_;
  const std::string column_family_name_;
383
};
S
Siying Dong 已提交
384

385
TEST_P(PlainTableDBTest, Flush) {
386 387
  for (size_t huge_page_tlb_size = 0; huge_page_tlb_size <= 2 * 1024 * 1024;
       huge_page_tlb_size += 2 * 1024 * 1024) {
388
    for (EncodingType encoding_type : {kPlain, kPrefix}) {
389 390
    for (int bloom_bits = 0; bloom_bits <= 117; bloom_bits += 117) {
      for (int total_order = 0; total_order <= 1; total_order++) {
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
        for (int store_index_in_file = 0; store_index_in_file <= 1;
             ++store_index_in_file) {
          Options options = CurrentOptions();
          options.create_if_missing = true;
          // Set only one bucket to force bucket conflict.
          // Test index interval for the same prefix to be 1, 2 and 4
          if (total_order) {
            options.prefix_extractor.reset();

            PlainTableOptions plain_table_options;
            plain_table_options.user_key_len = 0;
            plain_table_options.bloom_bits_per_key = bloom_bits;
            plain_table_options.hash_table_ratio = 0;
            plain_table_options.index_sparseness = 2;
            plain_table_options.huge_page_tlb_size = huge_page_tlb_size;
            plain_table_options.encoding_type = encoding_type;
            plain_table_options.full_scan_mode = false;
            plain_table_options.store_index_in_file = store_index_in_file;

            options.table_factory.reset(
                NewPlainTableFactory(plain_table_options));
          } else {
            PlainTableOptions plain_table_options;
            plain_table_options.user_key_len = 0;
            plain_table_options.bloom_bits_per_key = bloom_bits;
            plain_table_options.hash_table_ratio = 0.75;
            plain_table_options.index_sparseness = 16;
            plain_table_options.huge_page_tlb_size = huge_page_tlb_size;
            plain_table_options.encoding_type = encoding_type;
            plain_table_options.full_scan_mode = false;
            plain_table_options.store_index_in_file = store_index_in_file;

            options.table_factory.reset(
                NewPlainTableFactory(plain_table_options));
          }
          DestroyAndReopen(&options);
427 428 429 430 431
          uint64_t int_num;
          ASSERT_TRUE(dbfull()->GetIntProperty(
              "rocksdb.estimate-table-readers-mem", &int_num));
          ASSERT_EQ(int_num, 0U);

432 433 434 435 436
          ASSERT_OK(Put("1000000000000foo", "v1"));
          ASSERT_OK(Put("0000000000000bar", "v2"));
          ASSERT_OK(Put("1000000000000foo", "v3"));
          dbfull()->TEST_FlushMemTable();

437 438 439 440
          ASSERT_TRUE(dbfull()->GetIntProperty(
              "rocksdb.estimate-table-readers-mem", &int_num));
          ASSERT_GT(int_num, 0U);

441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
          TablePropertiesCollection ptc;
          reinterpret_cast<DB*>(dbfull())->GetPropertiesOfAllTables(&ptc);
          ASSERT_EQ(1U, ptc.size());
          auto row = ptc.begin();
          auto tp = row->second;

          if (!store_index_in_file) {
            ASSERT_EQ(total_order ? "4" : "12",
                      (tp->user_collected_properties)
                          .at("plain_table_hash_table_size"));
            ASSERT_EQ("0", (tp->user_collected_properties)
                               .at("plain_table_sub_index_size"));
          } else {
            ASSERT_EQ("0", (tp->user_collected_properties)
                               .at("plain_table_hash_table_size"));
            ASSERT_EQ("0", (tp->user_collected_properties)
                               .at("plain_table_sub_index_size"));
          }
          ASSERT_EQ("v3", Get("1000000000000foo"));
          ASSERT_EQ("v2", Get("0000000000000bar"));
        }
462
        }
463 464 465 466 467
      }
    }
  }
}

468
TEST_P(PlainTableDBTest, Flush2) {
469 470
  for (size_t huge_page_tlb_size = 0; huge_page_tlb_size <= 2 * 1024 * 1024;
       huge_page_tlb_size += 2 * 1024 * 1024) {
471
    for (EncodingType encoding_type : {kPlain, kPrefix}) {
472 473
    for (int bloom_bits = 0; bloom_bits <= 117; bloom_bits += 117) {
      for (int total_order = 0; total_order <= 1; total_order++) {
474 475 476 477 478 479 480 481 482
        for (int store_index_in_file = 0; store_index_in_file <= 1;
             ++store_index_in_file) {
          if (encoding_type == kPrefix && total_order) {
            continue;
          }
          if (!bloom_bits && store_index_in_file) {
            continue;
          }
          if (total_order && store_index_in_file) {
483 484
          continue;
        }
485 486 487 488 489
        bool expect_bloom_not_match = false;
        Options options = CurrentOptions();
        options.create_if_missing = true;
        // Set only one bucket to force bucket conflict.
        // Test index interval for the same prefix to be 1, 2 and 4
490
        PlainTableOptions plain_table_options;
491
        if (total_order) {
492
          options.prefix_extractor = nullptr;
S
Stanislau Hlebik 已提交
493 494
          plain_table_options.hash_table_ratio = 0;
          plain_table_options.index_sparseness = 2;
495
        } else {
S
Stanislau Hlebik 已提交
496 497
          plain_table_options.hash_table_ratio = 0.75;
          plain_table_options.index_sparseness = 16;
498
        }
499 500 501 502 503 504
        plain_table_options.user_key_len = kPlainTableVariableLength;
        plain_table_options.bloom_bits_per_key = bloom_bits;
        plain_table_options.huge_page_tlb_size = huge_page_tlb_size;
        plain_table_options.encoding_type = encoding_type;
        plain_table_options.store_index_in_file = store_index_in_file;
        options.table_factory.reset(new TestPlainTableFactory(
505 506
            &expect_bloom_not_match, plain_table_options,
            0 /* column_family_id */, kDefaultColumnFamilyName));
507

508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540
        DestroyAndReopen(&options);
        ASSERT_OK(Put("0000000000000bar", "b"));
        ASSERT_OK(Put("1000000000000foo", "v1"));
        dbfull()->TEST_FlushMemTable();

        ASSERT_OK(Put("1000000000000foo", "v2"));
        dbfull()->TEST_FlushMemTable();
        ASSERT_EQ("v2", Get("1000000000000foo"));

        ASSERT_OK(Put("0000000000000eee", "v3"));
        dbfull()->TEST_FlushMemTable();
        ASSERT_EQ("v3", Get("0000000000000eee"));

        ASSERT_OK(Delete("0000000000000bar"));
        dbfull()->TEST_FlushMemTable();
        ASSERT_EQ("NOT_FOUND", Get("0000000000000bar"));

        ASSERT_OK(Put("0000000000000eee", "v5"));
        ASSERT_OK(Put("9000000000000eee", "v5"));
        dbfull()->TEST_FlushMemTable();
        ASSERT_EQ("v5", Get("0000000000000eee"));

        // Test Bloom Filter
        if (bloom_bits > 0) {
          // Neither key nor value should exist.
          expect_bloom_not_match = true;
          ASSERT_EQ("NOT_FOUND", Get("5_not00000000bar"));
          // Key doesn't exist any more but prefix exists.
          if (total_order) {
            ASSERT_EQ("NOT_FOUND", Get("1000000000000not"));
            ASSERT_EQ("NOT_FOUND", Get("0000000000000not"));
          }
          expect_bloom_not_match = false;
541 542
        }
      }
543
      }
544
    }
545
    }
546
  }
S
Siying Dong 已提交
547 548
}

549
TEST_P(PlainTableDBTest, Iterator) {
550 551
  for (size_t huge_page_tlb_size = 0; huge_page_tlb_size <= 2 * 1024 * 1024;
       huge_page_tlb_size += 2 * 1024 * 1024) {
552
    for (EncodingType encoding_type : {kPlain, kPrefix}) {
553 554
    for (int bloom_bits = 0; bloom_bits <= 117; bloom_bits += 117) {
      for (int total_order = 0; total_order <= 1; total_order++) {
555 556 557
        if (encoding_type == kPrefix && total_order == 1) {
          continue;
        }
558 559 560 561 562 563 564
        bool expect_bloom_not_match = false;
        Options options = CurrentOptions();
        options.create_if_missing = true;
        // Set only one bucket to force bucket conflict.
        // Test index interval for the same prefix to be 1, 2 and 4
        if (total_order) {
          options.prefix_extractor = nullptr;
S
Stanislau Hlebik 已提交
565 566 567 568 569 570 571 572 573

          PlainTableOptions plain_table_options;
          plain_table_options.user_key_len = 16;
          plain_table_options.bloom_bits_per_key = bloom_bits;
          plain_table_options.hash_table_ratio = 0;
          plain_table_options.index_sparseness = 2;
          plain_table_options.huge_page_tlb_size = huge_page_tlb_size;
          plain_table_options.encoding_type = encoding_type;

574
          options.table_factory.reset(new TestPlainTableFactory(
575 576
              &expect_bloom_not_match, plain_table_options,
              0 /* column_family_id */, kDefaultColumnFamilyName));
577
        } else {
S
Stanislau Hlebik 已提交
578 579 580 581 582 583 584 585
          PlainTableOptions plain_table_options;
          plain_table_options.user_key_len = 16;
          plain_table_options.bloom_bits_per_key = bloom_bits;
          plain_table_options.hash_table_ratio = 0.75;
          plain_table_options.index_sparseness = 16;
          plain_table_options.huge_page_tlb_size = huge_page_tlb_size;
          plain_table_options.encoding_type = encoding_type;

586
          options.table_factory.reset(new TestPlainTableFactory(
587 588
              &expect_bloom_not_match, plain_table_options,
              0 /* column_family_id */, kDefaultColumnFamilyName));
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
        }
        DestroyAndReopen(&options);

        ASSERT_OK(Put("1000000000foo002", "v_2"));
        ASSERT_OK(Put("0000000000000bar", "random"));
        ASSERT_OK(Put("1000000000foo001", "v1"));
        ASSERT_OK(Put("3000000000000bar", "bar_v"));
        ASSERT_OK(Put("1000000000foo003", "v__3"));
        ASSERT_OK(Put("1000000000foo004", "v__4"));
        ASSERT_OK(Put("1000000000foo005", "v__5"));
        ASSERT_OK(Put("1000000000foo007", "v__7"));
        ASSERT_OK(Put("1000000000foo008", "v__8"));
        dbfull()->TEST_FlushMemTable();
        ASSERT_EQ("v1", Get("1000000000foo001"));
        ASSERT_EQ("v__3", Get("1000000000foo003"));
        Iterator* iter = dbfull()->NewIterator(ReadOptions());
        iter->Seek("1000000000foo000");
        ASSERT_TRUE(iter->Valid());
        ASSERT_EQ("1000000000foo001", iter->key().ToString());
        ASSERT_EQ("v1", iter->value().ToString());
609

610 611 612 613
        iter->Next();
        ASSERT_TRUE(iter->Valid());
        ASSERT_EQ("1000000000foo002", iter->key().ToString());
        ASSERT_EQ("v_2", iter->value().ToString());
614

615 616 617 618
        iter->Next();
        ASSERT_TRUE(iter->Valid());
        ASSERT_EQ("1000000000foo003", iter->key().ToString());
        ASSERT_EQ("v__3", iter->value().ToString());
619

620 621 622 623
        iter->Next();
        ASSERT_TRUE(iter->Valid());
        ASSERT_EQ("1000000000foo004", iter->key().ToString());
        ASSERT_EQ("v__4", iter->value().ToString());
624

625 626 627 628
        iter->Seek("3000000000000bar");
        ASSERT_TRUE(iter->Valid());
        ASSERT_EQ("3000000000000bar", iter->key().ToString());
        ASSERT_EQ("bar_v", iter->value().ToString());
629

630 631 632 633
        iter->Seek("1000000000foo000");
        ASSERT_TRUE(iter->Valid());
        ASSERT_EQ("1000000000foo001", iter->key().ToString());
        ASSERT_EQ("v1", iter->value().ToString());
634

635 636 637 638
        iter->Seek("1000000000foo005");
        ASSERT_TRUE(iter->Valid());
        ASSERT_EQ("1000000000foo005", iter->key().ToString());
        ASSERT_EQ("v__5", iter->value().ToString());
639

640 641 642 643
        iter->Seek("1000000000foo006");
        ASSERT_TRUE(iter->Valid());
        ASSERT_EQ("1000000000foo007", iter->key().ToString());
        ASSERT_EQ("v__7", iter->value().ToString());
644

645
        iter->Seek("1000000000foo008");
646
        ASSERT_TRUE(iter->Valid());
647 648
        ASSERT_EQ("1000000000foo008", iter->key().ToString());
        ASSERT_EQ("v__8", iter->value().ToString());
649

650 651 652 653
        if (total_order == 0) {
          iter->Seek("1000000000foo009");
          ASSERT_TRUE(iter->Valid());
          ASSERT_EQ("3000000000000bar", iter->key().ToString());
654 655
        }

656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673
        // Test Bloom Filter
        if (bloom_bits > 0) {
          if (!total_order) {
            // Neither key nor value should exist.
            expect_bloom_not_match = true;
            iter->Seek("2not000000000bar");
            ASSERT_TRUE(!iter->Valid());
            ASSERT_EQ("NOT_FOUND", Get("2not000000000bar"));
            expect_bloom_not_match = false;
          } else {
            expect_bloom_not_match = true;
            ASSERT_EQ("NOT_FOUND", Get("2not000000000bar"));
            expect_bloom_not_match = false;
          }
        }

        delete iter;
      }
674
    }
675
    }
676 677 678
  }
}

I
Igor Canadi 已提交
679
namespace {
680 681 682
std::string MakeLongKey(size_t length, char c) {
  return std::string(length, c);
}
I
Igor Canadi 已提交
683
}  // namespace
684

685
TEST_P(PlainTableDBTest, IteratorLargeKeys) {
686
  Options options = CurrentOptions();
S
Stanislau Hlebik 已提交
687 688 689 690 691 692 693

  PlainTableOptions plain_table_options;
  plain_table_options.user_key_len = 0;
  plain_table_options.bloom_bits_per_key = 0;
  plain_table_options.hash_table_ratio = 0;

  options.table_factory.reset(NewPlainTableFactory(plain_table_options));
694 695 696 697 698 699 700 701 702 703 704 705 706 707 708
  options.create_if_missing = true;
  options.prefix_extractor.reset();
  DestroyAndReopen(&options);

  std::string key_list[] = {
      MakeLongKey(30, '0'),
      MakeLongKey(16, '1'),
      MakeLongKey(32, '2'),
      MakeLongKey(60, '3'),
      MakeLongKey(90, '4'),
      MakeLongKey(50, '5'),
      MakeLongKey(26, '6')
  };

  for (size_t i = 0; i < 7; i++) {
709
    ASSERT_OK(Put(key_list[i], ToString(i)));
710 711 712 713
  }

  dbfull()->TEST_FlushMemTable();

714
  Iterator* iter = dbfull()->NewIterator(ReadOptions());
715 716 717 718 719
  iter->Seek(key_list[0]);

  for (size_t i = 0; i < 7; i++) {
    ASSERT_TRUE(iter->Valid());
    ASSERT_EQ(key_list[i], iter->key().ToString());
720
    ASSERT_EQ(ToString(i), iter->value().ToString());
721 722 723 724 725 726 727 728
    iter->Next();
  }

  ASSERT_TRUE(!iter->Valid());

  delete iter;
}

729 730 731 732 733 734
namespace {
std::string MakeLongKeyWithPrefix(size_t length, char c) {
  return "00000000" + std::string(length - 8, c);
}
}  // namespace

735
TEST_P(PlainTableDBTest, IteratorLargeKeysWithPrefix) {
736
  Options options = CurrentOptions();
S
Stanislau Hlebik 已提交
737 738 739 740 741 742 743 744 745 746

  PlainTableOptions plain_table_options;
  plain_table_options.user_key_len = 16;
  plain_table_options.bloom_bits_per_key = 0;
  plain_table_options.hash_table_ratio = 0.8;
  plain_table_options.index_sparseness = 3;
  plain_table_options.huge_page_tlb_size = 0;
  plain_table_options.encoding_type = kPrefix;

  options.table_factory.reset(NewPlainTableFactory(plain_table_options));
747 748 749 750 751 752 753 754 755 756
  options.create_if_missing = true;
  DestroyAndReopen(&options);

  std::string key_list[] = {
      MakeLongKeyWithPrefix(30, '0'), MakeLongKeyWithPrefix(16, '1'),
      MakeLongKeyWithPrefix(32, '2'), MakeLongKeyWithPrefix(60, '3'),
      MakeLongKeyWithPrefix(90, '4'), MakeLongKeyWithPrefix(50, '5'),
      MakeLongKeyWithPrefix(26, '6')};

  for (size_t i = 0; i < 7; i++) {
757
    ASSERT_OK(Put(key_list[i], ToString(i)));
758 759 760 761 762 763 764 765 766 767
  }

  dbfull()->TEST_FlushMemTable();

  Iterator* iter = dbfull()->NewIterator(ReadOptions());
  iter->Seek(key_list[0]);

  for (size_t i = 0; i < 7; i++) {
    ASSERT_TRUE(iter->Valid());
    ASSERT_EQ(key_list[i], iter->key().ToString());
768
    ASSERT_EQ(ToString(i), iter->value().ToString());
769 770 771 772 773 774 775 776
    iter->Next();
  }

  ASSERT_TRUE(!iter->Valid());

  delete iter;
}

777
TEST_P(PlainTableDBTest, IteratorReverseSuffixComparator) {
778 779 780 781
  Options options = CurrentOptions();
  options.create_if_missing = true;
  // Set only one bucket to force bucket conflict.
  // Test index interval for the same prefix to be 1, 2 and 4
782
  test::SimpleSuffixReverseComparator comp;
783 784 785
  options.comparator = &comp;
  DestroyAndReopen(&options);

S
Siying Dong 已提交
786 787 788 789 790 791 792 793 794 795 796 797
  ASSERT_OK(Put("1000000000foo002", "v_2"));
  ASSERT_OK(Put("0000000000000bar", "random"));
  ASSERT_OK(Put("1000000000foo001", "v1"));
  ASSERT_OK(Put("3000000000000bar", "bar_v"));
  ASSERT_OK(Put("1000000000foo003", "v__3"));
  ASSERT_OK(Put("1000000000foo004", "v__4"));
  ASSERT_OK(Put("1000000000foo005", "v__5"));
  ASSERT_OK(Put("1000000000foo007", "v__7"));
  ASSERT_OK(Put("1000000000foo008", "v__8"));
  dbfull()->TEST_FlushMemTable();
  ASSERT_EQ("v1", Get("1000000000foo001"));
  ASSERT_EQ("v__3", Get("1000000000foo003"));
798
  Iterator* iter = dbfull()->NewIterator(ReadOptions());
799
  iter->Seek("1000000000foo009");
S
Siying Dong 已提交
800
  ASSERT_TRUE(iter->Valid());
801 802
  ASSERT_EQ("1000000000foo008", iter->key().ToString());
  ASSERT_EQ("v__8", iter->value().ToString());
S
Siying Dong 已提交
803 804 805

  iter->Next();
  ASSERT_TRUE(iter->Valid());
806 807
  ASSERT_EQ("1000000000foo007", iter->key().ToString());
  ASSERT_EQ("v__7", iter->value().ToString());
S
Siying Dong 已提交
808 809 810

  iter->Next();
  ASSERT_TRUE(iter->Valid());
811 812
  ASSERT_EQ("1000000000foo005", iter->key().ToString());
  ASSERT_EQ("v__5", iter->value().ToString());
S
Siying Dong 已提交
813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830

  iter->Next();
  ASSERT_TRUE(iter->Valid());
  ASSERT_EQ("1000000000foo004", iter->key().ToString());
  ASSERT_EQ("v__4", iter->value().ToString());

  iter->Seek("3000000000000bar");
  ASSERT_TRUE(iter->Valid());
  ASSERT_EQ("3000000000000bar", iter->key().ToString());
  ASSERT_EQ("bar_v", iter->value().ToString());

  iter->Seek("1000000000foo005");
  ASSERT_TRUE(iter->Valid());
  ASSERT_EQ("1000000000foo005", iter->key().ToString());
  ASSERT_EQ("v__5", iter->value().ToString());

  iter->Seek("1000000000foo006");
  ASSERT_TRUE(iter->Valid());
831 832
  ASSERT_EQ("1000000000foo005", iter->key().ToString());
  ASSERT_EQ("v__5", iter->value().ToString());
S
Siying Dong 已提交
833 834 835 836 837 838

  iter->Seek("1000000000foo008");
  ASSERT_TRUE(iter->Valid());
  ASSERT_EQ("1000000000foo008", iter->key().ToString());
  ASSERT_EQ("v__8", iter->value().ToString());

839
  iter->Seek("1000000000foo000");
S
Siying Dong 已提交
840 841 842 843 844 845
  ASSERT_TRUE(iter->Valid());
  ASSERT_EQ("3000000000000bar", iter->key().ToString());

  delete iter;
}

846
TEST_P(PlainTableDBTest, HashBucketConflict) {
847 848 849 850 851 852 853
  for (size_t huge_page_tlb_size = 0; huge_page_tlb_size <= 2 * 1024 * 1024;
       huge_page_tlb_size += 2 * 1024 * 1024) {
    for (unsigned char i = 1; i <= 3; i++) {
      Options options = CurrentOptions();
      options.create_if_missing = true;
      // Set only one bucket to force bucket conflict.
      // Test index interval for the same prefix to be 1, 2 and 4
S
Stanislau Hlebik 已提交
854 855 856 857 858 859 860 861 862 863

      PlainTableOptions plain_table_options;
      plain_table_options.user_key_len = 16;
      plain_table_options.bloom_bits_per_key = 0;
      plain_table_options.hash_table_ratio = 0;
      plain_table_options.index_sparseness = 2 ^ i;
      plain_table_options.huge_page_tlb_size = huge_page_tlb_size;

      options.table_factory.reset(NewPlainTableFactory(plain_table_options));

864 865 866 867 868 869 870 871
      DestroyAndReopen(&options);
      ASSERT_OK(Put("5000000000000fo0", "v1"));
      ASSERT_OK(Put("5000000000000fo1", "v2"));
      ASSERT_OK(Put("5000000000000fo2", "v"));
      ASSERT_OK(Put("2000000000000fo0", "v3"));
      ASSERT_OK(Put("2000000000000fo1", "v4"));
      ASSERT_OK(Put("2000000000000fo2", "v"));
      ASSERT_OK(Put("2000000000000fo3", "v"));
872

873
      dbfull()->TEST_FlushMemTable();
874

875 876 877 878
      ASSERT_EQ("v1", Get("5000000000000fo0"));
      ASSERT_EQ("v2", Get("5000000000000fo1"));
      ASSERT_EQ("v3", Get("2000000000000fo0"));
      ASSERT_EQ("v4", Get("2000000000000fo1"));
879

880 881 882 883
      ASSERT_EQ("NOT_FOUND", Get("5000000000000bar"));
      ASSERT_EQ("NOT_FOUND", Get("2000000000000bar"));
      ASSERT_EQ("NOT_FOUND", Get("5000000000000fo8"));
      ASSERT_EQ("NOT_FOUND", Get("2000000000000fo8"));
884

885 886
      ReadOptions ro;
      Iterator* iter = dbfull()->NewIterator(ro);
887

888 889 890 891 892 893 894 895 896 897
      iter->Seek("5000000000000fo0");
      ASSERT_TRUE(iter->Valid());
      ASSERT_EQ("5000000000000fo0", iter->key().ToString());
      iter->Next();
      ASSERT_TRUE(iter->Valid());
      ASSERT_EQ("5000000000000fo1", iter->key().ToString());

      iter->Seek("5000000000000fo1");
      ASSERT_TRUE(iter->Valid());
      ASSERT_EQ("5000000000000fo1", iter->key().ToString());
898

899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916
      iter->Seek("2000000000000fo0");
      ASSERT_TRUE(iter->Valid());
      ASSERT_EQ("2000000000000fo0", iter->key().ToString());
      iter->Next();
      ASSERT_TRUE(iter->Valid());
      ASSERT_EQ("2000000000000fo1", iter->key().ToString());

      iter->Seek("2000000000000fo1");
      ASSERT_TRUE(iter->Valid());
      ASSERT_EQ("2000000000000fo1", iter->key().ToString());

      iter->Seek("2000000000000bar");
      ASSERT_TRUE(iter->Valid());
      ASSERT_EQ("2000000000000fo0", iter->key().ToString());

      iter->Seek("5000000000000bar");
      ASSERT_TRUE(iter->Valid());
      ASSERT_EQ("5000000000000fo0", iter->key().ToString());
917

918 919 920
      iter->Seek("2000000000000fo8");
      ASSERT_TRUE(!iter->Valid() ||
                  options.comparator->Compare(iter->key(), "20000001") > 0);
921

922 923
      iter->Seek("5000000000000fo8");
      ASSERT_TRUE(!iter->Valid());
924

925 926
      iter->Seek("1000000000000fo2");
      ASSERT_TRUE(!iter->Valid());
927

928 929
      iter->Seek("3000000000000fo2");
      ASSERT_TRUE(!iter->Valid());
930

931 932 933 934 935
      iter->Seek("8000000000000fo2");
      ASSERT_TRUE(!iter->Valid());

      delete iter;
    }
936 937
  }
}
S
Siying Dong 已提交
938

939
TEST_P(PlainTableDBTest, HashBucketConflictReverseSuffixComparator) {
940 941 942 943 944
  for (size_t huge_page_tlb_size = 0; huge_page_tlb_size <= 2 * 1024 * 1024;
       huge_page_tlb_size += 2 * 1024 * 1024) {
    for (unsigned char i = 1; i <= 3; i++) {
      Options options = CurrentOptions();
      options.create_if_missing = true;
945
      test::SimpleSuffixReverseComparator comp;
946 947 948
      options.comparator = &comp;
      // Set only one bucket to force bucket conflict.
      // Test index interval for the same prefix to be 1, 2 and 4
S
Stanislau Hlebik 已提交
949 950 951 952 953 954 955 956 957

      PlainTableOptions plain_table_options;
      plain_table_options.user_key_len = 16;
      plain_table_options.bloom_bits_per_key = 0;
      plain_table_options.hash_table_ratio = 0;
      plain_table_options.index_sparseness = 2 ^ i;
      plain_table_options.huge_page_tlb_size = huge_page_tlb_size;

      options.table_factory.reset(NewPlainTableFactory(plain_table_options));
958 959 960 961 962 963 964 965
      DestroyAndReopen(&options);
      ASSERT_OK(Put("5000000000000fo0", "v1"));
      ASSERT_OK(Put("5000000000000fo1", "v2"));
      ASSERT_OK(Put("5000000000000fo2", "v"));
      ASSERT_OK(Put("2000000000000fo0", "v3"));
      ASSERT_OK(Put("2000000000000fo1", "v4"));
      ASSERT_OK(Put("2000000000000fo2", "v"));
      ASSERT_OK(Put("2000000000000fo3", "v"));
966

967
      dbfull()->TEST_FlushMemTable();
968

969 970 971 972
      ASSERT_EQ("v1", Get("5000000000000fo0"));
      ASSERT_EQ("v2", Get("5000000000000fo1"));
      ASSERT_EQ("v3", Get("2000000000000fo0"));
      ASSERT_EQ("v4", Get("2000000000000fo1"));
973

974 975 976 977
      ASSERT_EQ("NOT_FOUND", Get("5000000000000bar"));
      ASSERT_EQ("NOT_FOUND", Get("2000000000000bar"));
      ASSERT_EQ("NOT_FOUND", Get("5000000000000fo8"));
      ASSERT_EQ("NOT_FOUND", Get("2000000000000fo8"));
978

979 980
      ReadOptions ro;
      Iterator* iter = dbfull()->NewIterator(ro);
981

982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998
      iter->Seek("5000000000000fo1");
      ASSERT_TRUE(iter->Valid());
      ASSERT_EQ("5000000000000fo1", iter->key().ToString());
      iter->Next();
      ASSERT_TRUE(iter->Valid());
      ASSERT_EQ("5000000000000fo0", iter->key().ToString());

      iter->Seek("5000000000000fo1");
      ASSERT_TRUE(iter->Valid());
      ASSERT_EQ("5000000000000fo1", iter->key().ToString());

      iter->Seek("2000000000000fo1");
      ASSERT_TRUE(iter->Valid());
      ASSERT_EQ("2000000000000fo1", iter->key().ToString());
      iter->Next();
      ASSERT_TRUE(iter->Valid());
      ASSERT_EQ("2000000000000fo0", iter->key().ToString());
999

1000 1001 1002
      iter->Seek("2000000000000fo1");
      ASSERT_TRUE(iter->Valid());
      ASSERT_EQ("2000000000000fo1", iter->key().ToString());
1003

1004 1005 1006 1007 1008 1009 1010
      iter->Seek("2000000000000var");
      ASSERT_TRUE(iter->Valid());
      ASSERT_EQ("2000000000000fo3", iter->key().ToString());

      iter->Seek("5000000000000var");
      ASSERT_TRUE(iter->Valid());
      ASSERT_EQ("5000000000000fo2", iter->key().ToString());
1011

1012 1013 1014 1015 1016
      std::string seek_key = "2000000000000bar";
      iter->Seek(seek_key);
      ASSERT_TRUE(!iter->Valid() ||
                  options.prefix_extractor->Transform(iter->key()) !=
                      options.prefix_extractor->Transform(seek_key));
1017

1018 1019
      iter->Seek("1000000000000fo2");
      ASSERT_TRUE(!iter->Valid());
1020

1021 1022 1023 1024 1025 1026 1027 1028
      iter->Seek("3000000000000fo2");
      ASSERT_TRUE(!iter->Valid());

      iter->Seek("8000000000000fo2");
      ASSERT_TRUE(!iter->Valid());

      delete iter;
    }
1029 1030
  }
}
S
Siying Dong 已提交
1031

1032
TEST_P(PlainTableDBTest, NonExistingKeyToNonEmptyBucket) {
1033 1034 1035 1036
  Options options = CurrentOptions();
  options.create_if_missing = true;
  // Set only one bucket to force bucket conflict.
  // Test index interval for the same prefix to be 1, 2 and 4
S
Stanislau Hlebik 已提交
1037 1038 1039 1040 1041 1042 1043
  PlainTableOptions plain_table_options;
  plain_table_options.user_key_len = 16;
  plain_table_options.bloom_bits_per_key = 0;
  plain_table_options.hash_table_ratio = 0;
  plain_table_options.index_sparseness = 5;

  options.table_factory.reset(NewPlainTableFactory(plain_table_options));
1044 1045 1046 1047
  DestroyAndReopen(&options);
  ASSERT_OK(Put("5000000000000fo0", "v1"));
  ASSERT_OK(Put("5000000000000fo1", "v2"));
  ASSERT_OK(Put("5000000000000fo2", "v3"));
S
Siying Dong 已提交
1048 1049 1050

  dbfull()->TEST_FlushMemTable();

1051 1052 1053 1054 1055 1056 1057
  ASSERT_EQ("v1", Get("5000000000000fo0"));
  ASSERT_EQ("v2", Get("5000000000000fo1"));
  ASSERT_EQ("v3", Get("5000000000000fo2"));

  ASSERT_EQ("NOT_FOUND", Get("8000000000000bar"));
  ASSERT_EQ("NOT_FOUND", Get("1000000000000bar"));

1058
  Iterator* iter = dbfull()->NewIterator(ReadOptions());
1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073

  iter->Seek("5000000000000bar");
  ASSERT_TRUE(iter->Valid());
  ASSERT_EQ("5000000000000fo0", iter->key().ToString());

  iter->Seek("5000000000000fo8");
  ASSERT_TRUE(!iter->Valid());

  iter->Seek("1000000000000fo2");
  ASSERT_TRUE(!iter->Valid());

  iter->Seek("8000000000000fo2");
  ASSERT_TRUE(!iter->Valid());

  delete iter;
S
Siying Dong 已提交
1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087
}

static std::string Key(int i) {
  char buf[100];
  snprintf(buf, sizeof(buf), "key_______%06d", i);
  return std::string(buf);
}

static std::string RandomString(Random* rnd, int len) {
  std::string r;
  test::RandomString(rnd, len, &r);
  return r;
}

1088
TEST_P(PlainTableDBTest, CompactionTrigger) {
S
Siying Dong 已提交
1089
  Options options = CurrentOptions();
1090
  options.write_buffer_size = 120 << 10;  // 100KB
S
Siying Dong 已提交
1091 1092 1093 1094 1095 1096 1097 1098 1099
  options.num_levels = 3;
  options.level0_file_num_compaction_trigger = 3;
  Reopen(&options);

  Random rnd(301);

  for (int num = 0; num < options.level0_file_num_compaction_trigger - 1;
      num++) {
    std::vector<std::string> values;
1100 1101 1102
    // Write 120KB (10 values, each 12K)
    for (int i = 0; i < 10; i++) {
      values.push_back(RandomString(&rnd, 12000));
S
Siying Dong 已提交
1103 1104
      ASSERT_OK(Put(Key(i), values[i]));
    }
1105
    ASSERT_OK(Put(Key(999), ""));
S
Siying Dong 已提交
1106 1107 1108 1109 1110 1111 1112 1113 1114 1115
    dbfull()->TEST_WaitForFlushMemTable();
    ASSERT_EQ(NumTableFilesAtLevel(0), num + 1);
  }

  //generate one more file in level-0, and should trigger level-0 compaction
  std::vector<std::string> values;
  for (int i = 0; i < 12; i++) {
    values.push_back(RandomString(&rnd, 10000));
    ASSERT_OK(Put(Key(i), values[i]));
  }
1116
  ASSERT_OK(Put(Key(999), ""));
S
Siying Dong 已提交
1117 1118 1119 1120 1121 1122
  dbfull()->TEST_WaitForCompact();

  ASSERT_EQ(NumTableFilesAtLevel(0), 0);
  ASSERT_EQ(NumTableFilesAtLevel(1), 1);
}

1123
TEST_P(PlainTableDBTest, AdaptiveTable) {
1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136
  Options options = CurrentOptions();
  options.create_if_missing = true;

  options.table_factory.reset(NewPlainTableFactory());
  DestroyAndReopen(&options);

  ASSERT_OK(Put("1000000000000foo", "v1"));
  ASSERT_OK(Put("0000000000000bar", "v2"));
  ASSERT_OK(Put("1000000000000foo", "v3"));
  dbfull()->TEST_FlushMemTable();

  options.create_if_missing = false;
  std::shared_ptr<TableFactory> dummy_factory;
1137 1138 1139 1140
  std::shared_ptr<TableFactory> block_based_factory(
      NewBlockBasedTableFactory());
  options.table_factory.reset(NewAdaptiveTableFactory(
      block_based_factory, dummy_factory, dummy_factory));
1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165
  Reopen(&options);
  ASSERT_EQ("v3", Get("1000000000000foo"));
  ASSERT_EQ("v2", Get("0000000000000bar"));

  ASSERT_OK(Put("2000000000000foo", "v4"));
  ASSERT_OK(Put("3000000000000bar", "v5"));
  dbfull()->TEST_FlushMemTable();
  ASSERT_EQ("v4", Get("2000000000000foo"));
  ASSERT_EQ("v5", Get("3000000000000bar"));

  Reopen(&options);
  ASSERT_EQ("v3", Get("1000000000000foo"));
  ASSERT_EQ("v2", Get("0000000000000bar"));
  ASSERT_EQ("v4", Get("2000000000000foo"));
  ASSERT_EQ("v5", Get("3000000000000bar"));

  options.table_factory.reset(NewBlockBasedTableFactory());
  Reopen(&options);
  ASSERT_NE("v3", Get("1000000000000foo"));

  options.table_factory.reset(NewPlainTableFactory());
  Reopen(&options);
  ASSERT_NE("v5", Get("3000000000000bar"));
}

1166 1167
INSTANTIATE_TEST_CASE_P(PlainTableDBTest, PlainTableDBTest, ::testing::Bool());

S
Siying Dong 已提交
1168 1169 1170
}  // namespace rocksdb

int main(int argc, char** argv) {
I
Igor Sugak 已提交
1171 1172
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
S
Siying Dong 已提交
1173
}
1174 1175 1176 1177

#else
#include <stdio.h>

1178
int main(int /*argc*/, char** /*argv*/) {
1179 1180 1181 1182 1183
  fprintf(stderr, "SKIPPED as plain table is not supported in ROCKSDB_LITE\n");
  return 0;
}

#endif  // !ROCKSDB_LITE