mock_table.cc 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. #include "table/mock_table.h"
  6. #include "db/dbformat.h"
  7. #include "env/composite_env_wrapper.h"
  8. #include "file/random_access_file_reader.h"
  9. #include "port/port.h"
  10. #include "rocksdb/table_properties.h"
  11. #include "table/get_context.h"
  12. #include "util/coding.h"
  13. namespace ROCKSDB_NAMESPACE {
  14. namespace mock {
  15. namespace {
  16. const InternalKeyComparator icmp_(BytewiseComparator());
  17. } // namespace
  18. stl_wrappers::KVMap MakeMockFile(
  19. std::initializer_list<std::pair<const std::string, std::string>> l) {
  20. return stl_wrappers::KVMap(l, stl_wrappers::LessOfComparator(&icmp_));
  21. }
  22. InternalIterator* MockTableReader::NewIterator(
  23. const ReadOptions&, const SliceTransform* /* prefix_extractor */,
  24. Arena* /*arena*/, bool /*skip_filters*/, TableReaderCaller /*caller*/,
  25. size_t /*compaction_readahead_size*/) {
  26. return new MockTableIterator(table_);
  27. }
  28. Status MockTableReader::Get(const ReadOptions&, const Slice& key,
  29. GetContext* get_context,
  30. const SliceTransform* /*prefix_extractor*/,
  31. bool /*skip_filters*/) {
  32. std::unique_ptr<MockTableIterator> iter(new MockTableIterator(table_));
  33. for (iter->Seek(key); iter->Valid(); iter->Next()) {
  34. ParsedInternalKey parsed_key;
  35. if (!ParseInternalKey(iter->key(), &parsed_key)) {
  36. return Status::Corruption(Slice());
  37. }
  38. bool dont_care __attribute__((__unused__));
  39. if (!get_context->SaveValue(parsed_key, iter->value(), &dont_care)) {
  40. break;
  41. }
  42. }
  43. return Status::OK();
  44. }
  45. std::shared_ptr<const TableProperties> MockTableReader::GetTableProperties()
  46. const {
  47. return std::shared_ptr<const TableProperties>(new TableProperties());
  48. }
  49. MockTableFactory::MockTableFactory() : next_id_(1) {}
  50. Status MockTableFactory::NewTableReader(
  51. const TableReaderOptions& /*table_reader_options*/,
  52. std::unique_ptr<RandomAccessFileReader>&& file, uint64_t /*file_size*/,
  53. std::unique_ptr<TableReader>* table_reader,
  54. bool /*prefetch_index_and_filter_in_cache*/) const {
  55. uint32_t id = GetIDFromFile(file.get());
  56. MutexLock lock_guard(&file_system_.mutex);
  57. auto it = file_system_.files.find(id);
  58. if (it == file_system_.files.end()) {
  59. return Status::IOError("Mock file not found");
  60. }
  61. table_reader->reset(new MockTableReader(it->second));
  62. return Status::OK();
  63. }
  64. TableBuilder* MockTableFactory::NewTableBuilder(
  65. const TableBuilderOptions& /*table_builder_options*/,
  66. uint32_t /*column_family_id*/, WritableFileWriter* file) const {
  67. uint32_t id = GetAndWriteNextID(file);
  68. return new MockTableBuilder(id, &file_system_);
  69. }
  70. Status MockTableFactory::CreateMockTable(Env* env, const std::string& fname,
  71. stl_wrappers::KVMap file_contents) {
  72. std::unique_ptr<WritableFile> file;
  73. auto s = env->NewWritableFile(fname, &file, EnvOptions());
  74. if (!s.ok()) {
  75. return s;
  76. }
  77. WritableFileWriter file_writer(NewLegacyWritableFileWrapper(std::move(file)),
  78. fname, EnvOptions());
  79. uint32_t id = GetAndWriteNextID(&file_writer);
  80. file_system_.files.insert({id, std::move(file_contents)});
  81. return Status::OK();
  82. }
  83. uint32_t MockTableFactory::GetAndWriteNextID(WritableFileWriter* file) const {
  84. uint32_t next_id = next_id_.fetch_add(1);
  85. char buf[4];
  86. EncodeFixed32(buf, next_id);
  87. file->Append(Slice(buf, 4));
  88. return next_id;
  89. }
  90. uint32_t MockTableFactory::GetIDFromFile(RandomAccessFileReader* file) const {
  91. char buf[4];
  92. Slice result;
  93. file->Read(0, 4, &result, buf);
  94. assert(result.size() == 4);
  95. return DecodeFixed32(buf);
  96. }
  97. void MockTableFactory::AssertSingleFile(
  98. const stl_wrappers::KVMap& file_contents) {
  99. ASSERT_EQ(file_system_.files.size(), 1U);
  100. ASSERT_EQ(file_contents, file_system_.files.begin()->second);
  101. }
  102. void MockTableFactory::AssertLatestFile(
  103. const stl_wrappers::KVMap& file_contents) {
  104. ASSERT_GE(file_system_.files.size(), 1U);
  105. auto latest = file_system_.files.end();
  106. --latest;
  107. if (file_contents != latest->second) {
  108. std::cout << "Wrong content! Content of latest file:" << std::endl;
  109. for (const auto& kv : latest->second) {
  110. ParsedInternalKey ikey;
  111. std::string key, value;
  112. std::tie(key, value) = kv;
  113. ParseInternalKey(Slice(key), &ikey);
  114. std::cout << ikey.DebugString(false) << " -> " << value << std::endl;
  115. }
  116. FAIL();
  117. }
  118. }
  119. } // namespace mock
  120. } // namespace ROCKSDB_NAMESPACE