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