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).
15 #include "db/version_edit.h"
16 #include "port/port.h"
17 #include "rocksdb/comparator.h"
18 #include "rocksdb/table.h"
19 #include "table/internal_iterator.h"
20 #include "table/table_builder.h"
21 #include "table/table_reader.h"
22 #include "test_util/testharness.h"
23 #include "test_util/testutil.h"
24 #include "util/kv_map.h"
25 #include "util/mutexlock.h"
27 namespace ROCKSDB_NAMESPACE
{
30 stl_wrappers::KVMap
MakeMockFile(
31 std::initializer_list
<std::pair
<const std::string
, std::string
>> l
= {});
33 struct MockTableFileSystem
{
35 std::map
<uint32_t, stl_wrappers::KVMap
> files
;
38 class MockTableReader
: public TableReader
{
40 explicit MockTableReader(const stl_wrappers::KVMap
& table
) : table_(table
) {}
42 InternalIterator
* NewIterator(const ReadOptions
&,
43 const SliceTransform
* prefix_extractor
,
44 Arena
* arena
, bool skip_filters
,
45 TableReaderCaller caller
,
46 size_t compaction_readahead_size
= 0) override
;
48 Status
Get(const ReadOptions
& readOptions
, const Slice
& key
,
49 GetContext
* get_context
, const SliceTransform
* prefix_extractor
,
50 bool skip_filters
= false) override
;
52 uint64_t ApproximateOffsetOf(const Slice
& /*key*/,
53 TableReaderCaller
/*caller*/) override
{
57 uint64_t ApproximateSize(const Slice
& /*start*/, const Slice
& /*end*/,
58 TableReaderCaller
/*caller*/) override
{
62 size_t ApproximateMemoryUsage() const override
{ return 0; }
64 void SetupForCompaction() override
{}
66 std::shared_ptr
<const TableProperties
> GetTableProperties() const override
;
71 const stl_wrappers::KVMap
& table_
;
74 class MockTableIterator
: public InternalIterator
{
76 explicit MockTableIterator(const stl_wrappers::KVMap
& table
) : table_(table
) {
80 bool Valid() const override
{ return itr_
!= table_
.end(); }
82 void SeekToFirst() override
{ itr_
= table_
.begin(); }
84 void SeekToLast() override
{
89 void Seek(const Slice
& target
) override
{
90 std::string
str_target(target
.data(), target
.size());
91 itr_
= table_
.lower_bound(str_target
);
94 void SeekForPrev(const Slice
& target
) override
{
95 std::string
str_target(target
.data(), target
.size());
96 itr_
= table_
.upper_bound(str_target
);
100 void Next() override
{ ++itr_
; }
102 void Prev() override
{
103 if (itr_
== table_
.begin()) {
110 Slice
key() const override
{ return Slice(itr_
->first
); }
112 Slice
value() const override
{ return Slice(itr_
->second
); }
114 Status
status() const override
{ return Status::OK(); }
117 const stl_wrappers::KVMap
& table_
;
118 stl_wrappers::KVMap::const_iterator itr_
;
121 class MockTableBuilder
: public TableBuilder
{
123 MockTableBuilder(uint32_t id
, MockTableFileSystem
* file_system
)
124 : id_(id
), file_system_(file_system
) {
125 table_
= MakeMockFile({});
128 // REQUIRES: Either Finish() or Abandon() has been called.
129 ~MockTableBuilder() {}
131 // Add key,value to the table being constructed.
132 // REQUIRES: key is after any previously added key according to comparator.
133 // REQUIRES: Finish(), Abandon() have not been called
134 void Add(const Slice
& key
, const Slice
& value
) override
{
135 table_
.insert({key
.ToString(), value
.ToString()});
138 // Return non-ok iff some error has been detected.
139 Status
status() const override
{ return Status::OK(); }
141 Status
Finish() override
{
142 MutexLock
lock_guard(&file_system_
->mutex
);
143 file_system_
->files
.insert({id_
, table_
});
147 void Abandon() override
{}
149 uint64_t NumEntries() const override
{ return table_
.size(); }
151 uint64_t FileSize() const override
{ return table_
.size(); }
153 TableProperties
GetTableProperties() const override
{
154 return TableProperties();
158 const std::string
& GetFileChecksum() const override
{ return file_checksum_
; }
159 // Get file checksum function name
160 const char* GetFileChecksumFuncName() const override
{
161 return kUnknownFileChecksumFuncName
.c_str();
166 MockTableFileSystem
* file_system_
;
167 stl_wrappers::KVMap table_
;
168 std::string file_checksum_
= kUnknownFileChecksum
;
171 class MockTableFactory
: public TableFactory
{
174 const char* Name() const override
{ return "MockTable"; }
175 Status
NewTableReader(
176 const TableReaderOptions
& table_reader_options
,
177 std::unique_ptr
<RandomAccessFileReader
>&& file
, uint64_t file_size
,
178 std::unique_ptr
<TableReader
>* table_reader
,
179 bool prefetch_index_and_filter_in_cache
= true) const override
;
180 TableBuilder
* NewTableBuilder(
181 const TableBuilderOptions
& table_builder_options
,
182 uint32_t column_familly_id
, WritableFileWriter
* file
) const override
;
184 // This function will directly create mock table instead of going through
185 // MockTableBuilder. file_contents has to have a format of <internal_key,
186 // value>. Those key-value pairs will then be inserted into the mock table.
187 Status
CreateMockTable(Env
* env
, const std::string
& fname
,
188 stl_wrappers::KVMap file_contents
);
190 virtual Status
SanitizeOptions(
191 const DBOptions
& /*db_opts*/,
192 const ColumnFamilyOptions
& /*cf_opts*/) const override
{
196 virtual std::string
GetPrintableTableOptions() const override
{
197 return std::string();
200 // This function will assert that only a single file exists and that the
201 // contents are equal to file_contents
202 void AssertSingleFile(const stl_wrappers::KVMap
& file_contents
);
203 void AssertLatestFile(const stl_wrappers::KVMap
& file_contents
);
206 uint32_t GetAndWriteNextID(WritableFileWriter
* file
) const;
207 uint32_t GetIDFromFile(RandomAccessFileReader
* file
) const;
209 mutable MockTableFileSystem file_system_
;
210 mutable std::atomic
<uint32_t> next_id_
;
214 } // namespace ROCKSDB_NAMESPACE