db_test_util.cc 43.7 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).
5 6 7 8 9
//
// 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.

10
#include "db/db_test_util.h"
11
#include "db/forward_iterator.h"
E
Ewout Prangsma 已提交
12
#include "rocksdb/env_encryption.h"
13 14 15 16 17 18 19 20 21 22

namespace rocksdb {

// Special Env used to delay background operations

SpecialEnv::SpecialEnv(Env* base)
    : EnvWrapper(base),
      rnd_(301),
      sleep_counter_(this),
      addon_time_(0),
23
      time_elapse_only_sleep_(false),
M
Maysam Yabandeh 已提交
24
      no_slowdown_(false) {
25 26 27 28 29 30 31 32 33
  delay_sstable_sync_.store(false, std::memory_order_release);
  drop_writes_.store(false, std::memory_order_release);
  no_space_.store(false, std::memory_order_release);
  non_writable_.store(false, std::memory_order_release);
  count_random_reads_ = false;
  count_sequential_reads_ = false;
  manifest_sync_error_.store(false, std::memory_order_release);
  manifest_write_error_.store(false, std::memory_order_release);
  log_write_error_.store(false, std::memory_order_release);
34
  random_file_open_counter_.store(0, std::memory_order_relaxed);
35 36
  delete_count_.store(0, std::memory_order_relaxed);
  num_open_wal_file_.store(0);
37 38 39 40 41 42 43 44
  log_write_slowdown_ = 0;
  bytes_written_ = 0;
  sync_counter_ = 0;
  non_writeable_rate_ = 0;
  new_writable_count_ = 0;
  non_writable_count_ = 0;
  table_write_callback_ = nullptr;
}
S
Siying Dong 已提交
45
#ifndef ROCKSDB_LITE
E
Ewout Prangsma 已提交
46
ROT13BlockCipher rot13Cipher_(16);
S
Siying Dong 已提交
47
#endif  // ROCKSDB_LITE
E
Ewout Prangsma 已提交
48

S
sdong 已提交
49
DBTestBase::DBTestBase(const std::string path)
Y
Yi Wu 已提交
50
    : mem_env_(!getenv("MEM_ENV") ? nullptr : new MockEnv(Env::Default())),
S
Siying Dong 已提交
51 52 53 54 55 56 57 58 59 60 61 62
#ifndef ROCKSDB_LITE
      encrypted_env_(
          !getenv("ENCRYPTED_ENV")
              ? nullptr
              : NewEncryptedEnv(mem_env_ ? mem_env_ : Env::Default(),
                                new CTREncryptionProvider(rot13Cipher_))),
#else
      encrypted_env_(nullptr),
#endif  // ROCKSDB_LITE
      env_(new SpecialEnv(encrypted_env_
                              ? encrypted_env_
                              : (mem_env_ ? mem_env_ : Env::Default()))),
Y
Yi Wu 已提交
63
      option_config_(kDefault) {
64 65 66 67
  env_->SetBackgroundThreads(1, Env::LOW);
  env_->SetBackgroundThreads(1, Env::HIGH);
  dbname_ = test::TmpDir(env_) + path;
  alternative_wal_dir_ = dbname_ + "/wal";
S
sdong 已提交
68
  alternative_db_log_dir_ = dbname_ + "/db_log_dir";
69
  auto options = CurrentOptions();
M
Maysam Yabandeh 已提交
70
  options.env = env_;
71 72 73 74 75 76 77
  auto delete_options = options;
  delete_options.wal_dir = alternative_wal_dir_;
  EXPECT_OK(DestroyDB(dbname_, delete_options));
  // Destroy it for not alternative WAL dir is used.
  EXPECT_OK(DestroyDB(dbname_, options));
  db_ = nullptr;
  Reopen(options);
78
  Random::GetTLSInstance()->Reset(0xdeadbeef);
79 80 81 82 83 84 85 86 87 88 89 90
}

DBTestBase::~DBTestBase() {
  rocksdb::SyncPoint::GetInstance()->DisableProcessing();
  rocksdb::SyncPoint::GetInstance()->LoadDependency({});
  rocksdb::SyncPoint::GetInstance()->ClearAllCallBacks();
  Close();
  Options options;
  options.db_paths.emplace_back(dbname_, 0);
  options.db_paths.emplace_back(dbname_ + "_2", 0);
  options.db_paths.emplace_back(dbname_ + "_3", 0);
  options.db_paths.emplace_back(dbname_ + "_4", 0);
M
Maysam Yabandeh 已提交
91
  options.env = env_;
I
Islam AbdelRahman 已提交
92 93 94 95 96 97

  if (getenv("KEEP_DB")) {
    printf("DB is still at %s\n", dbname_.c_str());
  } else {
    EXPECT_OK(DestroyDB(dbname_, options));
  }
98 99 100
  delete env_;
}

S
sdong 已提交
101
bool DBTestBase::ShouldSkipOptions(int option_config, int skip_mask) {
102 103
#ifdef ROCKSDB_LITE
    // These options are not supported in ROCKSDB_LITE
S
sdong 已提交
104 105 106 107 108 109 110 111 112
  if (option_config == kHashSkipList ||
      option_config == kPlainTableFirstBytePrefix ||
      option_config == kPlainTableCappedPrefix ||
      option_config == kPlainTableCappedPrefixNonMmap ||
      option_config == kPlainTableAllBytesPrefix ||
      option_config == kVectorRep || option_config == kHashLinkList ||
      option_config == kHashCuckoo || option_config == kUniversalCompaction ||
      option_config == kUniversalCompactionMultiLevel ||
      option_config == kUniversalSubcompactions ||
113 114
      option_config == kFIFOCompaction ||
      option_config == kConcurrentSkipList) {
S
sdong 已提交
115
    return true;
116 117 118
    }
#endif

119
    if ((skip_mask & kSkipUniversalCompaction) &&
S
sdong 已提交
120 121 122
        (option_config == kUniversalCompaction ||
         option_config == kUniversalCompactionMultiLevel)) {
      return true;
123
    }
S
sdong 已提交
124 125
    if ((skip_mask & kSkipMergePut) && option_config == kMergePut) {
      return true;
126 127
    }
    if ((skip_mask & kSkipNoSeekToLast) &&
S
sdong 已提交
128 129
        (option_config == kHashLinkList || option_config == kHashSkipList)) {
      return true;
130 131
    }
    if ((skip_mask & kSkipPlainTable) &&
S
sdong 已提交
132 133 134 135 136
        (option_config == kPlainTableAllBytesPrefix ||
         option_config == kPlainTableFirstBytePrefix ||
         option_config == kPlainTableCappedPrefix ||
         option_config == kPlainTableCappedPrefixNonMmap)) {
      return true;
137 138
    }
    if ((skip_mask & kSkipHashIndex) &&
S
sdong 已提交
139 140 141
        (option_config == kBlockBasedTableWithPrefixHashIndex ||
         option_config == kBlockBasedTableWithWholeKeyHashIndex)) {
      return true;
142
    }
S
sdong 已提交
143 144
    if ((skip_mask & kSkipHashCuckoo) && (option_config == kHashCuckoo)) {
      return true;
145
    }
S
sdong 已提交
146 147
    if ((skip_mask & kSkipFIFOCompaction) && option_config == kFIFOCompaction) {
      return true;
148
    }
S
sdong 已提交
149 150 151 152 153 154 155 156 157 158 159
    if ((skip_mask & kSkipMmapReads) && option_config == kWalDirAndMmapReads) {
      return true;
    }
    return false;
}

// Switch to a fresh database with the next option configuration to
// test.  Return false if there are no more configurations to test.
bool DBTestBase::ChangeOptions(int skip_mask) {
  for (option_config_++; option_config_ < kEnd; option_config_++) {
    if (ShouldSkipOptions(option_config_, skip_mask)) {
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
      continue;
    }
    break;
  }

  if (option_config_ >= kEnd) {
    Destroy(last_options_);
    return false;
  } else {
    auto options = CurrentOptions();
    options.create_if_missing = true;
    DestroyAndReopen(options);
    return true;
  }
}

176
// Switch between different compaction styles.
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
bool DBTestBase::ChangeCompactOptions() {
  if (option_config_ == kDefault) {
    option_config_ = kUniversalCompaction;
    Destroy(last_options_);
    auto options = CurrentOptions();
    options.create_if_missing = true;
    TryReopen(options);
    return true;
  } else if (option_config_ == kUniversalCompaction) {
    option_config_ = kUniversalCompactionMultiLevel;
    Destroy(last_options_);
    auto options = CurrentOptions();
    options.create_if_missing = true;
    TryReopen(options);
    return true;
192 193 194 195
  } else if (option_config_ == kUniversalCompactionMultiLevel) {
    option_config_ = kLevelSubcompactions;
    Destroy(last_options_);
    auto options = CurrentOptions();
196 197 198 199 200 201 202 203
    assert(options.max_subcompactions > 1);
    TryReopen(options);
    return true;
  } else if (option_config_ == kLevelSubcompactions) {
    option_config_ = kUniversalSubcompactions;
    Destroy(last_options_);
    auto options = CurrentOptions();
    assert(options.max_subcompactions > 1);
204 205
    TryReopen(options);
    return true;
206 207 208 209 210
  } else {
    return false;
  }
}

S
Siying Dong 已提交
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
// Switch between different WAL settings
bool DBTestBase::ChangeWalOptions() {
  if (option_config_ == kDefault) {
    option_config_ = kDBLogDir;
    Destroy(last_options_);
    auto options = CurrentOptions();
    Destroy(options);
    options.create_if_missing = true;
    TryReopen(options);
    return true;
  } else if (option_config_ == kDBLogDir) {
    option_config_ = kWalDirAndMmapReads;
    Destroy(last_options_);
    auto options = CurrentOptions();
    Destroy(options);
    options.create_if_missing = true;
    TryReopen(options);
    return true;
  } else if (option_config_ == kWalDirAndMmapReads) {
    option_config_ = kRecycleLogFiles;
    Destroy(last_options_);
    auto options = CurrentOptions();
    Destroy(options);
    TryReopen(options);
    return true;
  } else {
    return false;
  }
}

241 242 243 244 245 246
// Switch between different filter policy
// Jump from kDefault to kFilter to kFullFilter
bool DBTestBase::ChangeFilterOptions() {
  if (option_config_ == kDefault) {
    option_config_ = kFilter;
  } else if (option_config_ == kFilter) {
247
    option_config_ = kFullFilterWithNewTableReaderForCompactions;
M
Maysam Yabandeh 已提交
248 249
  } else if (option_config_ == kFullFilterWithNewTableReaderForCompactions) {
    option_config_ = kPartitionedFilterWithNewTableReaderForCompactions;
250 251 252 253 254 255 256 257 258 259 260 261 262
  } else {
    return false;
  }
  Destroy(last_options_);

  auto options = CurrentOptions();
  options.create_if_missing = true;
  TryReopen(options);
  return true;
}

// Return the current option configuration.
Options DBTestBase::CurrentOptions(
Y
Yi Wu 已提交
263 264 265 266 267 268 269 270 271 272 273
    const anon::OptionsOverride& options_override) const {
  return GetOptions(option_config_, GetDefaultOptions(), options_override);
}

Options DBTestBase::CurrentOptions(
    const Options& default_options,
    const anon::OptionsOverride& options_override) const {
  return GetOptions(option_config_, default_options, options_override);
}

Options DBTestBase::GetDefaultOptions() {
274
  Options options;
275
  options.write_buffer_size = 4090 * 4096;
S
sdong 已提交
276 277
  options.target_file_size_base = 2 * 1024 * 1024;
  options.max_bytes_for_level_base = 10 * 1024 * 1024;
S
sdong 已提交
278 279 280
  options.max_open_files = 5000;
  options.wal_recovery_mode = WALRecoveryMode::kTolerateCorruptedTailRecords;
  options.compaction_pri = CompactionPri::kByCompensatedSize;
Y
Yi Wu 已提交
281
  return options;
282 283
}

Y
Yi Wu 已提交
284 285 286
Options DBTestBase::GetOptions(
    int option_config, const Options& default_options,
    const anon::OptionsOverride& options_override) const {
A
Andres Notzli 已提交
287
  // this redundant copy is to minimize code change w/o having lint error.
Y
Yi Wu 已提交
288
  Options options = default_options;
289 290
  BlockBasedTableOptions table_options;
  bool set_block_based_table_factory = true;
291 292
#if !defined(OS_MACOSX) && !defined(OS_WIN) && !defined(OS_SOLARIS) && \
    !defined(OS_AIX)
293 294
  rocksdb::SyncPoint::GetInstance()->ClearCallBack(
      "NewRandomAccessFile:O_DIRECT");
295
  rocksdb::SyncPoint::GetInstance()->ClearCallBack("NewWritableFile:O_DIRECT");
296 297
#endif

E
Ewout Prangsma 已提交
298
  bool can_allow_mmap = IsMemoryMappedAccessSupported();
Y
Yi Wu 已提交
299
  switch (option_config) {
300
#ifndef ROCKSDB_LITE
301 302
    case kHashSkipList:
      options.prefix_extractor.reset(NewFixedPrefixTransform(1));
S
sdong 已提交
303
      options.memtable_factory.reset(NewHashSkipListRepFactory(16));
304
      options.allow_concurrent_memtable_write = false;
305 306 307 308
      break;
    case kPlainTableFirstBytePrefix:
      options.table_factory.reset(new PlainTableFactory());
      options.prefix_extractor.reset(NewFixedPrefixTransform(1));
E
Ewout Prangsma 已提交
309
      options.allow_mmap_reads = can_allow_mmap;
310 311 312 313 314 315
      options.max_sequential_skip_in_iterations = 999999;
      set_block_based_table_factory = false;
      break;
    case kPlainTableCappedPrefix:
      options.table_factory.reset(new PlainTableFactory());
      options.prefix_extractor.reset(NewCappedPrefixTransform(8));
E
Ewout Prangsma 已提交
316
      options.allow_mmap_reads = can_allow_mmap;
317 318 319
      options.max_sequential_skip_in_iterations = 999999;
      set_block_based_table_factory = false;
      break;
320 321 322 323 324 325 326
    case kPlainTableCappedPrefixNonMmap:
      options.table_factory.reset(new PlainTableFactory());
      options.prefix_extractor.reset(NewCappedPrefixTransform(8));
      options.allow_mmap_reads = false;
      options.max_sequential_skip_in_iterations = 999999;
      set_block_based_table_factory = false;
      break;
327 328 329
    case kPlainTableAllBytesPrefix:
      options.table_factory.reset(new PlainTableFactory());
      options.prefix_extractor.reset(NewNoopTransform());
E
Ewout Prangsma 已提交
330
      options.allow_mmap_reads = can_allow_mmap;
331 332 333
      options.max_sequential_skip_in_iterations = 999999;
      set_block_based_table_factory = false;
      break;
334 335
    case kVectorRep:
      options.memtable_factory.reset(new VectorRepFactory(100));
336
      options.allow_concurrent_memtable_write = false;
337 338 339 340 341
      break;
    case kHashLinkList:
      options.prefix_extractor.reset(NewFixedPrefixTransform(1));
      options.memtable_factory.reset(
          NewHashLinkListRepFactory(4, 0, 3, true, 4));
342
      options.allow_concurrent_memtable_write = false;
343 344 345 346
      break;
    case kHashCuckoo:
      options.memtable_factory.reset(
          NewHashCuckooRepFactory(options.write_buffer_size));
347
      options.allow_concurrent_memtable_write = false;
348 349
      break;
#endif  // ROCKSDB_LITE
350 351 352 353 354 355
    case kMergePut:
      options.merge_operator = MergeOperators::CreatePutOperator();
      break;
    case kFilter:
      table_options.filter_policy.reset(NewBloomFilterPolicy(10, true));
      break;
356
    case kFullFilterWithNewTableReaderForCompactions:
357
      table_options.filter_policy.reset(NewBloomFilterPolicy(10, false));
358
      options.new_table_reader_for_compaction_inputs = true;
359
      options.compaction_readahead_size = 10 * 1024 * 1024;
360
      break;
M
Maysam Yabandeh 已提交
361 362 363 364 365 366 367 368
    case kPartitionedFilterWithNewTableReaderForCompactions:
      table_options.filter_policy.reset(NewBloomFilterPolicy(10, false));
      table_options.partition_filters = true;
      table_options.index_type =
          BlockBasedTableOptions::IndexType::kTwoLevelIndexSearch;
      options.new_table_reader_for_compaction_inputs = true;
      options.compaction_readahead_size = 10 * 1024 * 1024;
      break;
369 370 371 372 373 374 375
    case kUncompressed:
      options.compression = kNoCompression;
      break;
    case kNumLevel_3:
      options.num_levels = 3;
      break;
    case kDBLogDir:
S
sdong 已提交
376
      options.db_log_dir = alternative_db_log_dir_;
377 378 379 380 381
      break;
    case kWalDirAndMmapReads:
      options.wal_dir = alternative_wal_dir_;
      // mmap reads should be orthogonal to WalDir setting, so we piggyback to
      // this option config to test mmap reads as well
E
Ewout Prangsma 已提交
382
      options.allow_mmap_reads = can_allow_mmap;
383 384 385
      break;
    case kManifestFileSize:
      options.max_manifest_file_size = 50;  // 50 bytes
386
      break;
387
    case kPerfOptions:
388 389
      options.soft_rate_limit = 2.0;
      options.delayed_write_rate = 8 * 1024 * 1024;
390
      options.report_bg_io_stats = true;
391 392 393 394 395 396 397 398 399 400 401
      // TODO(3.13) -- test more options
      break;
    case kUniversalCompaction:
      options.compaction_style = kCompactionStyleUniversal;
      options.num_levels = 1;
      break;
    case kUniversalCompactionMultiLevel:
      options.compaction_style = kCompactionStyleUniversal;
      options.num_levels = 8;
      break;
    case kCompressedBlockCache:
E
Ewout Prangsma 已提交
402
      options.allow_mmap_writes = can_allow_mmap;
S
sdong 已提交
403
      table_options.block_cache_compressed = NewLRUCache(8 * 1024 * 1024);
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
      break;
    case kInfiniteMaxOpenFiles:
      options.max_open_files = -1;
      break;
    case kxxHashChecksum: {
      table_options.checksum = kxxHash;
      break;
    }
    case kFIFOCompaction: {
      options.compaction_style = kCompactionStyleFIFO;
      break;
    }
    case kBlockBasedTableWithPrefixHashIndex: {
      table_options.index_type = BlockBasedTableOptions::kHashSearch;
      options.prefix_extractor.reset(NewFixedPrefixTransform(1));
      break;
    }
    case kBlockBasedTableWithWholeKeyHashIndex: {
      table_options.index_type = BlockBasedTableOptions::kHashSearch;
      options.prefix_extractor.reset(NewNoopTransform());
      break;
    }
M
Maysam Yabandeh 已提交
426 427 428 429 430
    case kBlockBasedTableWithPartitionedIndex: {
      table_options.index_type = BlockBasedTableOptions::kTwoLevelIndexSearch;
      options.prefix_extractor.reset(NewNoopTransform());
      break;
    }
431 432 433 434
    case kBlockBasedTableWithIndexRestartInterval: {
      table_options.index_block_restart_interval = 8;
      break;
    }
435 436 437 438 439 440 441 442 443
    case kOptimizeFiltersForHits: {
      options.optimize_filters_for_hits = true;
      set_block_based_table_factory = true;
      break;
    }
    case kRowCache: {
      options.row_cache = NewLRUCache(1024 * 1024);
      break;
    }
444 445 446 447
    case kRecycleLogFiles: {
      options.recycle_log_file_num = 2;
      break;
    }
448
    case kLevelSubcompactions: {
449 450 451 452 453 454 455
      options.max_subcompactions = 4;
      break;
    }
    case kUniversalSubcompactions: {
      options.compaction_style = kCompactionStyleUniversal;
      options.num_levels = 8;
      options.max_subcompactions = 4;
456 457
      break;
    }
458 459 460 461 462
    case kConcurrentSkipList: {
      options.allow_concurrent_memtable_write = true;
      options.enable_write_thread_adaptive_yield = true;
      break;
    }
463 464 465 466 467
    case kDirectIO: {
      options.use_direct_reads = true;
      options.use_direct_io_for_flush_and_compaction = true;
      options.compaction_readahead_size = 2 * 1024 * 1024;
#if !defined(OS_MACOSX) && !defined(OS_WIN) && !defined(OS_SOLARIS) && \
Z
zach shipko 已提交
468
    !defined(OS_AIX) && !defined(OS_OPENBSD)
469 470 471 472 473 474 475 476 477 478 479 480 481 482
      rocksdb::SyncPoint::GetInstance()->SetCallBack(
          "NewWritableFile:O_DIRECT", [&](void* arg) {
            int* val = static_cast<int*>(arg);
            *val &= ~O_DIRECT;
          });
      rocksdb::SyncPoint::GetInstance()->SetCallBack(
          "NewRandomAccessFile:O_DIRECT", [&](void* arg) {
            int* val = static_cast<int*>(arg);
            *val &= ~O_DIRECT;
          });
      rocksdb::SyncPoint::GetInstance()->EnableProcessing();
#endif
      break;
    }
Y
Yi Wu 已提交
483 484 485 486
    case kPipelinedWrite: {
      options.enable_pipelined_write = true;
      break;
    }
487 488
    case kConcurrentWALWrites: {
      // This options optimize 2PC commit path
489
      options.two_write_queues = true;
490 491 492
      options.manual_wal_flush = true;
      break;
    }
493 494 495 496 497 498 499

    default:
      break;
  }

  if (options_override.filter_policy) {
    table_options.filter_policy = options_override.filter_policy;
M
Maysam Yabandeh 已提交
500
    table_options.partition_filters = options_override.partition_filters;
M
Maysam Yabandeh 已提交
501
    table_options.metadata_block_size = options_override.metadata_block_size;
502 503 504 505 506 507
  }
  if (set_block_based_table_factory) {
    options.table_factory.reset(NewBlockBasedTableFactory(table_options));
  }
  options.env = env_;
  options.create_if_missing = true;
508
  options.fail_if_options_file_error = true;
509 510 511 512
  return options;
}

void DBTestBase::CreateColumnFamilies(const std::vector<std::string>& cfs,
S
sdong 已提交
513
                                      const Options& options) {
514 515 516 517 518 519 520 521 522
  ColumnFamilyOptions cf_opts(options);
  size_t cfi = handles_.size();
  handles_.resize(cfi + cfs.size());
  for (auto cf : cfs) {
    ASSERT_OK(db_->CreateColumnFamily(cf_opts, cf, &handles_[cfi++]));
  }
}

void DBTestBase::CreateAndReopenWithCF(const std::vector<std::string>& cfs,
S
sdong 已提交
523
                                       const Options& options) {
524 525 526 527 528 529 530
  CreateColumnFamilies(cfs, options);
  std::vector<std::string> cfs_plus_default = cfs;
  cfs_plus_default.insert(cfs_plus_default.begin(), kDefaultColumnFamilyName);
  ReopenWithColumnFamilies(cfs_plus_default, options);
}

void DBTestBase::ReopenWithColumnFamilies(const std::vector<std::string>& cfs,
S
sdong 已提交
531
                                          const std::vector<Options>& options) {
532 533 534 535
  ASSERT_OK(TryReopenWithColumnFamilies(cfs, options));
}

void DBTestBase::ReopenWithColumnFamilies(const std::vector<std::string>& cfs,
S
sdong 已提交
536
                                          const Options& options) {
537 538 539 540
  ASSERT_OK(TryReopenWithColumnFamilies(cfs, options));
}

Status DBTestBase::TryReopenWithColumnFamilies(
S
sdong 已提交
541
    const std::vector<std::string>& cfs, const std::vector<Options>& options) {
542 543 544 545 546 547 548 549 550 551 552
  Close();
  EXPECT_EQ(cfs.size(), options.size());
  std::vector<ColumnFamilyDescriptor> column_families;
  for (size_t i = 0; i < cfs.size(); ++i) {
    column_families.push_back(ColumnFamilyDescriptor(cfs[i], options[i]));
  }
  DBOptions db_opts = DBOptions(options[0]);
  return DB::Open(db_opts, dbname_, column_families, &handles_, &db_);
}

Status DBTestBase::TryReopenWithColumnFamilies(
S
sdong 已提交
553
    const std::vector<std::string>& cfs, const Options& options) {
554 555 556 557 558 559 560 561 562 563 564
  Close();
  std::vector<Options> v_opts(cfs.size(), options);
  return TryReopenWithColumnFamilies(cfs, v_opts);
}

void DBTestBase::Reopen(const Options& options) {
  ASSERT_OK(TryReopen(options));
}

void DBTestBase::Close() {
  for (auto h : handles_) {
565
    db_->DestroyColumnFamilyHandle(h);
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588
  }
  handles_.clear();
  delete db_;
  db_ = nullptr;
}

void DBTestBase::DestroyAndReopen(const Options& options) {
  // Destroy using last options
  Destroy(last_options_);
  ASSERT_OK(TryReopen(options));
}

void DBTestBase::Destroy(const Options& options) {
  Close();
  ASSERT_OK(DestroyDB(dbname_, options));
}

Status DBTestBase::ReadOnlyReopen(const Options& options) {
  return DB::OpenForReadOnly(options, dbname_, &db_);
}

Status DBTestBase::TryReopen(const Options& options) {
  Close();
589 590 591 592 593 594 595
  last_options_.table_factory.reset();
  // Note: operator= is an unsafe approach here since it destructs shared_ptr in
  // the same order of their creation, in contrast to destructors which
  // destructs them in the opposite order of creation. One particular problme is
  // that the cache destructor might invoke callback functions that use Option
  // members such as statistics. To work around this problem, we manually call
  // destructor of table_facotry which eventually clears the block cache.
596 597 598 599
  last_options_ = options;
  return DB::Open(options, dbname_, &db_);
}

A
Aaron Gao 已提交
600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615
bool DBTestBase::IsDirectIOSupported() {
  EnvOptions env_options;
  env_options.use_mmap_writes = false;
  env_options.use_direct_writes = true;
  std::string tmp = TempFileName(dbname_, 999);
  Status s;
  {
    unique_ptr<WritableFile> file;
    s = env_->NewWritableFile(tmp, &file, env_options);
  }
  if (s.ok()) {
    s = env_->DeleteFile(tmp);
  }
  return s.ok();
}

E
Ewout Prangsma 已提交
616 617 618 619
bool DBTestBase::IsMemoryMappedAccessSupported() const {
  return (!encrypted_env_);
}

620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
Status DBTestBase::Flush(int cf) {
  if (cf == 0) {
    return db_->Flush(FlushOptions());
  } else {
    return db_->Flush(FlushOptions(), handles_[cf]);
  }
}

Status DBTestBase::Put(const Slice& k, const Slice& v, WriteOptions wo) {
  if (kMergePut == option_config_) {
    return db_->Merge(wo, k, v);
  } else {
    return db_->Put(wo, k, v);
  }
}

Status DBTestBase::Put(int cf, const Slice& k, const Slice& v,
S
sdong 已提交
637
                       WriteOptions wo) {
638 639 640 641 642 643 644
  if (kMergePut == option_config_) {
    return db_->Merge(wo, handles_[cf], k, v);
  } else {
    return db_->Put(wo, handles_[cf], k, v);
  }
}

645 646 647 648 649 650 651 652 653
Status DBTestBase::Merge(const Slice& k, const Slice& v, WriteOptions wo) {
  return db_->Merge(wo, k, v);
}

Status DBTestBase::Merge(int cf, const Slice& k, const Slice& v,
                         WriteOptions wo) {
  return db_->Merge(wo, handles_[cf], k, v);
}

654 655 656 657 658 659 660 661
Status DBTestBase::Delete(const std::string& k) {
  return db_->Delete(WriteOptions(), k);
}

Status DBTestBase::Delete(int cf, const std::string& k) {
  return db_->Delete(WriteOptions(), handles_[cf], k);
}

A
Andres Noetzli 已提交
662 663 664 665 666 667 668 669
Status DBTestBase::SingleDelete(const std::string& k) {
  return db_->SingleDelete(WriteOptions(), k);
}

Status DBTestBase::SingleDelete(int cf, const std::string& k) {
  return db_->SingleDelete(WriteOptions(), handles_[cf], k);
}

670 671 672 673
bool DBTestBase::SetPreserveDeletesSequenceNumber(SequenceNumber sn) {
  return db_->SetPreserveDeletesSequenceNumber(sn);
}

674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
std::string DBTestBase::Get(const std::string& k, const Snapshot* snapshot) {
  ReadOptions options;
  options.verify_checksums = true;
  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;
}

std::string DBTestBase::Get(int cf, const std::string& k,
S
sdong 已提交
689
                            const Snapshot* snapshot) {
690 691 692 693 694 695 696 697 698 699 700 701 702
  ReadOptions options;
  options.verify_checksums = true;
  options.snapshot = snapshot;
  std::string result;
  Status s = db_->Get(options, handles_[cf], k, &result);
  if (s.IsNotFound()) {
    result = "NOT_FOUND";
  } else if (!s.ok()) {
    result = s.ToString();
  }
  return result;
}

703 704 705 706 707 708 709
Status DBTestBase::Get(const std::string& k, PinnableSlice* v) {
  ReadOptions options;
  options.verify_checksums = true;
  Status s = dbfull()->Get(options, dbfull()->DefaultColumnFamily(), k, v);
  return s;
}

710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752
uint64_t DBTestBase::GetNumSnapshots() {
  uint64_t int_num;
  EXPECT_TRUE(dbfull()->GetIntProperty("rocksdb.num-snapshots", &int_num));
  return int_num;
}

uint64_t DBTestBase::GetTimeOldestSnapshots() {
  uint64_t int_num;
  EXPECT_TRUE(
      dbfull()->GetIntProperty("rocksdb.oldest-snapshot-time", &int_num));
  return int_num;
}

// Return a string that contains all key,value pairs in order,
// formatted like "(k1->v1)(k2->v2)".
std::string DBTestBase::Contents(int cf) {
  std::vector<std::string> forward;
  std::string result;
  Iterator* iter = (cf == 0) ? db_->NewIterator(ReadOptions())
                             : db_->NewIterator(ReadOptions(), handles_[cf]);
  for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
    std::string s = IterStatus(iter);
    result.push_back('(');
    result.append(s);
    result.push_back(')');
    forward.push_back(s);
  }

  // Check reverse iteration results are the reverse of forward results
  unsigned int matched = 0;
  for (iter->SeekToLast(); iter->Valid(); iter->Prev()) {
    EXPECT_LT(matched, forward.size());
    EXPECT_EQ(IterStatus(iter), forward[forward.size() - matched - 1]);
    matched++;
  }
  EXPECT_EQ(matched, forward.size());

  delete iter;
  return result;
}

std::string DBTestBase::AllEntriesFor(const Slice& user_key, int cf) {
  Arena arena;
A
Andrew Kryczka 已提交
753
  auto options = CurrentOptions();
A
Andrew Kryczka 已提交
754 755
  InternalKeyComparator icmp(options.comparator);
  RangeDelAggregator range_del_agg(icmp, {} /* snapshots */);
756 757
  ScopedArenaIterator iter;
  if (cf == 0) {
A
Andrew Kryczka 已提交
758
    iter.set(dbfull()->NewInternalIterator(&arena, &range_del_agg));
759
  } else {
A
Andrew Kryczka 已提交
760 761
    iter.set(
        dbfull()->NewInternalIterator(&arena, &range_del_agg, handles_[cf]));
762 763 764 765 766 767 768 769 770 771 772 773 774 775
  }
  InternalKey target(user_key, kMaxSequenceNumber, kTypeValue);
  iter->Seek(target.Encode());
  std::string result;
  if (!iter->status().ok()) {
    result = iter->status().ToString();
  } else {
    result = "[ ";
    bool first = true;
    while (iter->Valid()) {
      ParsedInternalKey ikey(Slice(), 0, kTypeValue);
      if (!ParseInternalKey(iter->key(), &ikey)) {
        result += "CORRUPTED";
      } else {
776
        if (!last_options_.comparator->Equal(ikey.user_key, user_key)) {
777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793
          break;
        }
        if (!first) {
          result += ", ";
        }
        first = false;
        switch (ikey.type) {
          case kTypeValue:
            result += iter->value().ToString();
            break;
          case kTypeMerge:
            // keep it the same as kTypeValue for testing kMergePut
            result += iter->value().ToString();
            break;
          case kTypeDeletion:
            result += "DEL";
            break;
A
Andres Noetzli 已提交
794 795 796
          case kTypeSingleDeletion:
            result += "SDEL";
            break;
797 798 799 800 801 802 803 804 805 806 807 808 809 810 811
          default:
            assert(false);
            break;
        }
      }
      iter->Next();
    }
    if (!first) {
      result += " ";
    }
    result += "]";
  }
  return result;
}

812
#ifndef ROCKSDB_LITE
813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850
int DBTestBase::NumSortedRuns(int cf) {
  ColumnFamilyMetaData cf_meta;
  if (cf == 0) {
    db_->GetColumnFamilyMetaData(&cf_meta);
  } else {
    db_->GetColumnFamilyMetaData(handles_[cf], &cf_meta);
  }
  int num_sr = static_cast<int>(cf_meta.levels[0].files.size());
  for (size_t i = 1U; i < cf_meta.levels.size(); i++) {
    if (cf_meta.levels[i].files.size() > 0) {
      num_sr++;
    }
  }
  return num_sr;
}

uint64_t DBTestBase::TotalSize(int cf) {
  ColumnFamilyMetaData cf_meta;
  if (cf == 0) {
    db_->GetColumnFamilyMetaData(&cf_meta);
  } else {
    db_->GetColumnFamilyMetaData(handles_[cf], &cf_meta);
  }
  return cf_meta.size;
}

uint64_t DBTestBase::SizeAtLevel(int level) {
  std::vector<LiveFileMetaData> metadata;
  db_->GetLiveFilesMetaData(&metadata);
  uint64_t sum = 0;
  for (const auto& m : metadata) {
    if (m.level == level) {
      sum += m.size;
    }
  }
  return sum;
}

V
Vasili Svirski 已提交
851
size_t DBTestBase::TotalLiveFiles(int cf) {
852 853 854 855 856 857
  ColumnFamilyMetaData cf_meta;
  if (cf == 0) {
    db_->GetColumnFamilyMetaData(&cf_meta);
  } else {
    db_->GetColumnFamilyMetaData(handles_[cf], &cf_meta);
  }
V
Vasili Svirski 已提交
858
  size_t num_files = 0;
859 860 861 862 863 864
  for (auto& level : cf_meta.levels) {
    num_files += level.files.size();
  }
  return num_files;
}

865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884
size_t DBTestBase::CountLiveFiles() {
  std::vector<LiveFileMetaData> metadata;
  db_->GetLiveFilesMetaData(&metadata);
  return metadata.size();
}

int DBTestBase::NumTableFilesAtLevel(int level, int cf) {
  std::string property;
  if (cf == 0) {
    // default cfd
    EXPECT_TRUE(db_->GetProperty(
        "rocksdb.num-files-at-level" + NumberToString(level), &property));
  } else {
    EXPECT_TRUE(db_->GetProperty(
        handles_[cf], "rocksdb.num-files-at-level" + NumberToString(level),
        &property));
  }
  return atoi(property.c_str());
}

885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900
double DBTestBase::CompressionRatioAtLevel(int level, int cf) {
  std::string property;
  if (cf == 0) {
    // default cfd
    EXPECT_TRUE(db_->GetProperty(
        "rocksdb.compression-ratio-at-level" + NumberToString(level),
        &property));
  } else {
    EXPECT_TRUE(db_->GetProperty(
        handles_[cf],
        "rocksdb.compression-ratio-at-level" + NumberToString(level),
        &property));
  }
  return std::stod(property);
}

901 902
int DBTestBase::TotalTableFiles(int cf, int levels) {
  if (levels == -1) {
903
    levels = (cf == 0) ? db_->NumberLevels() : db_->NumberLevels(handles_[1]);
904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929
  }
  int result = 0;
  for (int level = 0; level < levels; level++) {
    result += NumTableFilesAtLevel(level, cf);
  }
  return result;
}

// Return spread of files per level
std::string DBTestBase::FilesPerLevel(int cf) {
  int num_levels =
      (cf == 0) ? db_->NumberLevels() : db_->NumberLevels(handles_[1]);
  std::string result;
  size_t last_non_zero_offset = 0;
  for (int level = 0; level < num_levels; level++) {
    int f = NumTableFilesAtLevel(level, cf);
    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;
}
Y
Yi Wu 已提交
930
#endif  // !ROCKSDB_LITE
931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955

size_t DBTestBase::CountFiles() {
  std::vector<std::string> files;
  env_->GetChildren(dbname_, &files);

  std::vector<std::string> logfiles;
  if (dbname_ != last_options_.wal_dir) {
    env_->GetChildren(last_options_.wal_dir, &logfiles);
  }

  return files.size() + logfiles.size();
}

uint64_t DBTestBase::Size(const Slice& start, const Slice& limit, int cf) {
  Range r(start, limit);
  uint64_t size;
  if (cf == 0) {
    db_->GetApproximateSizes(&r, 1, &size);
  } else {
    db_->GetApproximateSizes(handles_[1], &r, 1, &size);
  }
  return size;
}

void DBTestBase::Compact(int cf, const Slice& start, const Slice& limit,
S
sdong 已提交
956
                         uint32_t target_path_id) {
957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972
  CompactRangeOptions compact_options;
  compact_options.target_path_id = target_path_id;
  ASSERT_OK(db_->CompactRange(compact_options, handles_[cf], &start, &limit));
}

void DBTestBase::Compact(int cf, const Slice& start, const Slice& limit) {
  ASSERT_OK(
      db_->CompactRange(CompactRangeOptions(), handles_[cf], &start, &limit));
}

void DBTestBase::Compact(const Slice& start, const Slice& limit) {
  ASSERT_OK(db_->CompactRange(CompactRangeOptions(), &start, &limit));
}

// Do n memtable compactions, each of which produces an sstable
// covering the range [small,large].
S
sdong 已提交
973 974
void DBTestBase::MakeTables(int n, const std::string& small,
                            const std::string& large, int cf) {
975 976 977 978
  for (int i = 0; i < n; i++) {
    ASSERT_OK(Put(cf, small, "begin"));
    ASSERT_OK(Put(cf, large, "end"));
    ASSERT_OK(Flush(cf));
979
    MoveFilesToLevel(n - i - 1, cf);
980 981 982 983 984
  }
}

// Prevent pushing of new sstables into deeper levels by adding
// tables that cover a specified range to all levels.
S
sdong 已提交
985 986
void DBTestBase::FillLevels(const std::string& smallest,
                            const std::string& largest, int cf) {
987 988 989
  MakeTables(db_->NumberLevels(handles_[cf]), smallest, largest, cf);
}

990 991 992 993 994 995 996 997 998 999
void DBTestBase::MoveFilesToLevel(int level, int cf) {
  for (int l = 0; l < level; ++l) {
    if (cf > 0) {
      dbfull()->TEST_CompactRange(l, nullptr, nullptr, handles_[cf]);
    } else {
      dbfull()->TEST_CompactRange(l, nullptr, nullptr);
    }
  }
}

Y
Yi Wu 已提交
1000
#ifndef ROCKSDB_LITE
1001 1002 1003
void DBTestBase::DumpFileCounts(const char* label) {
  fprintf(stderr, "---\n%s:\n", label);
  fprintf(stderr, "maxoverlap: %" PRIu64 "\n",
S
sdong 已提交
1004
          dbfull()->TEST_MaxNextLevelOverlappingBytes());
1005 1006 1007 1008 1009 1010 1011
  for (int level = 0; level < db_->NumberLevels(); level++) {
    int num = NumTableFilesAtLevel(level);
    if (num > 0) {
      fprintf(stderr, "  level %3d : %d files\n", level, num);
    }
  }
}
Y
Yi Wu 已提交
1012
#endif  // !ROCKSDB_LITE
1013 1014 1015 1016 1017 1018 1019

std::string DBTestBase::DumpSSTableList() {
  std::string property;
  db_->GetProperty("rocksdb.sstables", &property);
  return property;
}

D
dyniusz 已提交
1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031
void DBTestBase::GetSstFiles(std::string path,
                             std::vector<std::string>* files) {
  env_->GetChildren(path, files);

  files->erase(
      std::remove_if(files->begin(), files->end(), [](std::string name) {
        uint64_t number;
        FileType type;
        return !(ParseFileName(name, &number, &type) && type == kTableFile);
      }), files->end());
}

1032 1033
int DBTestBase::GetSstFileCount(std::string path) {
  std::vector<std::string> files;
D
dyniusz 已提交
1034 1035
  GetSstFiles(path, &files);
  return static_cast<int>(files.size());
1036 1037
}

1038 1039 1040
// this will generate non-overlapping files since it keeps increasing key_idx
void DBTestBase::GenerateNewFile(int cf, Random* rnd, int* key_idx,
                                 bool nowait) {
K
krad 已提交
1041
  for (int i = 0; i < KNumKeysByGenerateNewFile; i++) {
1042 1043 1044 1045 1046 1047 1048 1049 1050
    ASSERT_OK(Put(cf, Key(*key_idx), RandomString(rnd, (i == 99) ? 1 : 990)));
    (*key_idx)++;
  }
  if (!nowait) {
    dbfull()->TEST_WaitForFlushMemTable();
    dbfull()->TEST_WaitForCompact();
  }
}

1051 1052
// this will generate non-overlapping files since it keeps increasing key_idx
void DBTestBase::GenerateNewFile(Random* rnd, int* key_idx, bool nowait) {
K
krad 已提交
1053
  for (int i = 0; i < KNumKeysByGenerateNewFile; i++) {
1054
    ASSERT_OK(Put(Key(*key_idx), RandomString(rnd, (i == 99) ? 1 : 990)));
1055 1056 1057 1058 1059 1060 1061 1062
    (*key_idx)++;
  }
  if (!nowait) {
    dbfull()->TEST_WaitForFlushMemTable();
    dbfull()->TEST_WaitForCompact();
  }
}

1063 1064
const int DBTestBase::kNumKeysByGenerateNewRandomFile = 51;

1065
void DBTestBase::GenerateNewRandomFile(Random* rnd, bool nowait) {
1066
  for (int i = 0; i < kNumKeysByGenerateNewRandomFile; i++) {
1067
    ASSERT_OK(Put("key" + RandomString(rnd, 7), RandomString(rnd, 2000)));
1068
  }
1069
  ASSERT_OK(Put("key" + RandomString(rnd, 7), RandomString(rnd, 200)));
1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115
  if (!nowait) {
    dbfull()->TEST_WaitForFlushMemTable();
    dbfull()->TEST_WaitForCompact();
  }
}

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

Options DBTestBase::OptionsForLogIterTest() {
  Options options = CurrentOptions();
  options.create_if_missing = true;
  options.WAL_ttl_seconds = 1000;
  return options;
}

std::string DBTestBase::DummyString(size_t len, char c) {
  return std::string(len, c);
}

void DBTestBase::VerifyIterLast(std::string expected_key, int cf) {
  Iterator* iter;
  ReadOptions ro;
  if (cf == 0) {
    iter = db_->NewIterator(ro);
  } else {
    iter = db_->NewIterator(ro, handles_[cf]);
  }
  iter->SeekToLast();
  ASSERT_EQ(IterStatus(iter), expected_key);
  delete iter;
}

// Used to test InplaceUpdate

// If previous value is nullptr or delta is > than previous value,
//   sets newValue with delta
// If previous value is not empty,
//   updates previous value with 'b' string of previous value size - 1.
S
sdong 已提交
1116 1117 1118 1119
UpdateStatus DBTestBase::updateInPlaceSmallerSize(char* prevValue,
                                                  uint32_t* prevSize,
                                                  Slice delta,
                                                  std::string* newValue) {
1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130
  if (prevValue == nullptr) {
    *newValue = std::string(delta.size(), 'c');
    return UpdateStatus::UPDATED;
  } else {
    *prevSize = *prevSize - 1;
    std::string str_b = std::string(*prevSize, 'b');
    memcpy(prevValue, str_b.c_str(), str_b.size());
    return UpdateStatus::UPDATED_INPLACE;
  }
}

S
sdong 已提交
1131 1132 1133 1134
UpdateStatus DBTestBase::updateInPlaceSmallerVarintSize(char* prevValue,
                                                        uint32_t* prevSize,
                                                        Slice delta,
                                                        std::string* newValue) {
1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145
  if (prevValue == nullptr) {
    *newValue = std::string(delta.size(), 'c');
    return UpdateStatus::UPDATED;
  } else {
    *prevSize = 1;
    std::string str_b = std::string(*prevSize, 'b');
    memcpy(prevValue, str_b.c_str(), str_b.size());
    return UpdateStatus::UPDATED_INPLACE;
  }
}

1146 1147
UpdateStatus DBTestBase::updateInPlaceLargerSize(char* prevValue,
                                                 uint32_t* prevSize,
S
sdong 已提交
1148 1149
                                                 Slice delta,
                                                 std::string* newValue) {
1150 1151 1152 1153
  *newValue = std::string(delta.size(), 'c');
  return UpdateStatus::UPDATED;
}

1154 1155 1156
UpdateStatus DBTestBase::updateInPlaceNoAction(char* prevValue,
                                               uint32_t* prevSize, Slice delta,
                                               std::string* newValue) {
1157 1158 1159 1160 1161 1162
  return UpdateStatus::UPDATE_FAILED;
}

// Utility method to test InplaceUpdate
void DBTestBase::validateNumberOfEntries(int numValues, int cf) {
  Arena arena;
A
Andrew Kryczka 已提交
1163
  auto options = CurrentOptions();
A
Andrew Kryczka 已提交
1164 1165
  InternalKeyComparator icmp(options.comparator);
  RangeDelAggregator range_del_agg(icmp, {} /* snapshots */);
1166 1167 1168
  // This should be defined after range_del_agg so that it destructs the
  // assigned iterator before it range_del_agg is already destructed.
  ScopedArenaIterator iter;
1169
  if (cf != 0) {
A
Andrew Kryczka 已提交
1170 1171
    iter.set(
        dbfull()->NewInternalIterator(&arena, &range_del_agg, handles_[cf]));
1172
  } else {
A
Andrew Kryczka 已提交
1173
    iter.set(dbfull()->NewInternalIterator(&arena, &range_del_agg));
1174 1175 1176 1177 1178 1179
  }
  iter->SeekToFirst();
  ASSERT_EQ(iter->status().ok(), true);
  int seq = numValues;
  while (iter->Valid()) {
    ParsedInternalKey ikey;
1180
    ikey.clear();
1181 1182 1183 1184 1185 1186 1187 1188 1189
    ASSERT_EQ(ParseInternalKey(iter->key(), &ikey), true);

    // checks sequence number for updates
    ASSERT_EQ(ikey.sequence, (unsigned)seq--);
    iter->Next();
  }
  ASSERT_EQ(0, seq);
}

S
sdong 已提交
1190 1191
void DBTestBase::CopyFile(const std::string& source,
                          const std::string& destination, uint64_t size) {
1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213
  const EnvOptions soptions;
  unique_ptr<SequentialFile> srcfile;
  ASSERT_OK(env_->NewSequentialFile(source, &srcfile, soptions));
  unique_ptr<WritableFile> destfile;
  ASSERT_OK(env_->NewWritableFile(destination, &destfile, soptions));

  if (size == 0) {
    // default argument means copy everything
    ASSERT_OK(env_->GetFileSize(source, &size));
  }

  char buffer[4096];
  Slice slice;
  while (size > 0) {
    uint64_t one = std::min(uint64_t(sizeof(buffer)), size);
    ASSERT_OK(srcfile->Read(one, &slice, buffer));
    ASSERT_OK(destfile->Append(slice));
    size -= slice.size();
  }
  ASSERT_OK(destfile->Close());
}

1214 1215
std::unordered_map<std::string, uint64_t> DBTestBase::GetAllSSTFiles(
    uint64_t* total_size) {
1216 1217
  std::unordered_map<std::string, uint64_t> res;

1218 1219 1220
  if (total_size) {
    *total_size = 0;
  }
1221 1222 1223 1224 1225 1226 1227 1228 1229 1230
  std::vector<std::string> files;
  env_->GetChildren(dbname_, &files);
  for (auto& file_name : files) {
    uint64_t number;
    FileType type;
    std::string file_path = dbname_ + "/" + file_name;
    if (ParseFileName(file_name, &number, &type) && type == kTableFile) {
      uint64_t file_size = 0;
      env_->GetFileSize(file_path, &file_size);
      res[file_path] = file_size;
1231 1232 1233
      if (total_size) {
        *total_size += file_size;
      }
1234 1235 1236 1237 1238
    }
  }
  return res;
}

Y
Yi Wu 已提交
1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255
std::vector<std::uint64_t> DBTestBase::ListTableFiles(Env* env,
                                                      const std::string& path) {
  std::vector<std::string> files;
  std::vector<uint64_t> file_numbers;
  env->GetChildren(path, &files);
  uint64_t number;
  FileType type;
  for (size_t i = 0; i < files.size(); ++i) {
    if (ParseFileName(files[i], &number, &type)) {
      if (type == kTableFile) {
        file_numbers.push_back(number);
      }
    }
  }
  return file_numbers;
}

1256
void DBTestBase::VerifyDBFromMap(std::map<std::string, std::string> true_data,
1257 1258
                                 size_t* total_reads_res, bool tailing_iter,
                                 std::map<std::string, Status> status) {
1259 1260
  size_t total_reads = 0;

1261
  for (auto& kv : true_data) {
1262 1263 1264 1265 1266 1267 1268
    Status s = status[kv.first];
    if (s.ok()) {
      ASSERT_EQ(Get(kv.first), kv.second);
    } else {
      std::string value;
      ASSERT_EQ(s, db_->Get(ReadOptions(), kv.first, &value));
    }
1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280
    total_reads++;
  }

  // Normal Iterator
  {
    int iter_cnt = 0;
    ReadOptions ro;
    ro.total_order_seek = true;
    Iterator* iter = db_->NewIterator(ro);
    // Verify Iterator::Next()
    iter_cnt = 0;
    auto data_iter = true_data.begin();
1281
    Status s;
1282 1283
    for (iter->SeekToFirst(); iter->Valid(); iter->Next(), data_iter++) {
      ASSERT_EQ(iter->key().ToString(), data_iter->first);
1284 1285 1286 1287 1288 1289 1290 1291
      Status current_status = status[data_iter->first];
      if (!current_status.ok()) {
        s = current_status;
      }
      ASSERT_EQ(iter->status(), s);
      if (current_status.ok()) {
        ASSERT_EQ(iter->value().ToString(), data_iter->second);
      }
1292 1293 1294 1295 1296
      iter_cnt++;
      total_reads++;
    }
    ASSERT_EQ(data_iter, true_data.end()) << iter_cnt << " / "
                                          << true_data.size();
1297
    delete iter;
1298 1299

    // Verify Iterator::Prev()
1300 1301
    // Use a new iterator to make sure its status is clean.
    iter = db_->NewIterator(ro);
1302
    iter_cnt = 0;
1303
    s = Status::OK();
1304 1305 1306
    auto data_rev = true_data.rbegin();
    for (iter->SeekToLast(); iter->Valid(); iter->Prev(), data_rev++) {
      ASSERT_EQ(iter->key().ToString(), data_rev->first);
1307 1308 1309 1310 1311 1312 1313 1314
      Status current_status = status[data_rev->first];
      if (!current_status.ok()) {
        s = current_status;
      }
      ASSERT_EQ(iter->status(), s);
      if (current_status.ok()) {
        ASSERT_EQ(iter->value().ToString(), data_rev->second);
      }
1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328
      iter_cnt++;
      total_reads++;
    }
    ASSERT_EQ(data_rev, true_data.rend()) << iter_cnt << " / "
                                          << true_data.size();

    // Verify Iterator::Seek()
    for (auto kv : true_data) {
      iter->Seek(kv.first);
      ASSERT_EQ(kv.first, iter->key().ToString());
      ASSERT_EQ(kv.second, iter->value().ToString());
      total_reads++;
    }
    delete iter;
1329 1330
  }

1331
  if (tailing_iter) {
1332
#ifndef ROCKSDB_LITE
1333 1334 1335 1336 1337 1338
    // Tailing iterator
    int iter_cnt = 0;
    ReadOptions ro;
    ro.tailing = true;
    ro.total_order_seek = true;
    Iterator* iter = db_->NewIterator(ro);
1339

1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360
    // Verify ForwardIterator::Next()
    iter_cnt = 0;
    auto data_iter = true_data.begin();
    for (iter->SeekToFirst(); iter->Valid(); iter->Next(), data_iter++) {
      ASSERT_EQ(iter->key().ToString(), data_iter->first);
      ASSERT_EQ(iter->value().ToString(), data_iter->second);
      iter_cnt++;
      total_reads++;
    }
    ASSERT_EQ(data_iter, true_data.end()) << iter_cnt << " / "
                                          << true_data.size();

    // Verify ForwardIterator::Seek()
    for (auto kv : true_data) {
      iter->Seek(kv.first);
      ASSERT_EQ(kv.first, iter->key().ToString());
      ASSERT_EQ(kv.second, iter->value().ToString());
      total_reads++;
    }

    delete iter;
1361
#endif  // ROCKSDB_LITE
1362
  }
1363 1364 1365 1366

  if (total_reads_res) {
    *total_reads_res = total_reads;
  }
1367 1368
}

1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387
void DBTestBase::VerifyDBInternal(
    std::vector<std::pair<std::string, std::string>> true_data) {
  Arena arena;
  InternalKeyComparator icmp(last_options_.comparator);
  RangeDelAggregator range_del_agg(icmp, {});
  auto iter = dbfull()->NewInternalIterator(&arena, &range_del_agg);
  iter->SeekToFirst();
  for (auto p : true_data) {
    ASSERT_TRUE(iter->Valid());
    ParsedInternalKey ikey;
    ASSERT_TRUE(ParseInternalKey(iter->key(), &ikey));
    ASSERT_EQ(p.first, ikey.user_key);
    ASSERT_EQ(p.second, iter->value());
    iter->Next();
  };
  ASSERT_FALSE(iter->Valid());
  iter->~InternalIterator();
}

Y
Yi Wu 已提交
1388
#ifndef ROCKSDB_LITE
1389

Y
Yi Wu 已提交
1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401
uint64_t DBTestBase::GetNumberOfSstFilesForColumnFamily(
    DB* db, std::string column_family_name) {
  std::vector<LiveFileMetaData> metadata;
  db->GetLiveFilesMetaData(&metadata);
  uint64_t result = 0;
  for (auto& fileMetadata : metadata) {
    result += (fileMetadata.column_family_name == column_family_name);
  }
  return result;
}
#endif  // ROCKSDB_LITE

1402
}  // namespace rocksdb