YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/rocksdb/db/db_table_properties_test.cc
Line
Count
Source (jump to first uncovered line)
1
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2
//  This source code is licensed under the BSD-style license found in the
3
//  LICENSE file in the root directory of this source tree. An additional grant
4
//  of patent rights can be found in the PATENTS file in the same directory.
5
//
6
// The following only applies to changes made to this file as part of YugaByte development.
7
//
8
// Portions Copyright (c) YugaByte, Inc.
9
//
10
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
11
// in compliance with the License.  You may obtain a copy of the License at
12
//
13
// http://www.apache.org/licenses/LICENSE-2.0
14
//
15
// Unless required by applicable law or agreed to in writing, software distributed under the License
16
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
17
// or implied.  See the License for the specific language governing permissions and limitations
18
// under the License.
19
//
20
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
21
// Use of this source code is governed by a BSD-style license that can be
22
// found in the LICENSE file. See the AUTHORS file for names of contributors.
23
24
#include <unordered_set>
25
#include <vector>
26
27
#include "yb/rocksdb/db/db_test_util.h"
28
#include "yb/rocksdb/port/stack_trace.h"
29
30
#ifndef ROCKSDB_LITE
31
32
namespace rocksdb {
33
34
// A helper function that ensures the table properties returned in
35
// `GetPropertiesOfAllTablesTest` is correct.
36
// This test assumes entries size is different for each of the tables.
37
namespace {
38
39
3
void VerifyTableProperties(DB* db, uint64_t expected_entries_size) {
40
3
  TablePropertiesCollection props;
41
3
  ASSERT_OK(db->GetPropertiesOfAllTables(&props));
42
43
3
  ASSERT_EQ(4U, props.size());
44
3
  std::unordered_set<uint64_t> unique_entries;
45
46
  // Indirect test
47
3
  uint64_t sum = 0;
48
12
  for (const auto& item : props) {
49
12
    unique_entries.insert(item.second->num_entries);
50
12
    sum += item.second->num_entries;
51
12
  }
52
53
3
  ASSERT_EQ(props.size(), unique_entries.size());
54
3
  ASSERT_EQ(expected_entries_size, sum);
55
3
}
56
}  // namespace
57
58
class DBTablePropertiesTest : public DBTestBase {
59
 public:
60
2
  DBTablePropertiesTest() : DBTestBase("/db_table_properties_test") {}
61
  TablePropertiesCollection TestGetPropertiesOfTablesInRange(
62
      std::vector<Range> ranges, std::size_t* num_properties = nullptr,
63
      std::size_t* num_files = nullptr);
64
};
65
66
1
TEST_F(DBTablePropertiesTest, GetPropertiesOfAllTablesTest) {
67
1
  Options options = CurrentOptions();
68
1
  options.level0_file_num_compaction_trigger = 8;
69
1
  Reopen(options);
70
  // Create 4 tables
71
5
  for (int table = 0; table < 4; ++table) {
72
50
    for (int i = 0; i < 10 + table; ++i) {
73
46
      ASSERT_OK(db_->Put(WriteOptions(), ToString(table * 100 + i), "val"));
74
46
    }
75
4
    ASSERT_OK(db_->Flush(FlushOptions()));
76
4
  }
77
78
  // 1. Read table properties directly from file
79
1
  Reopen(options);
80
1
  VerifyTableProperties(db_, 10 + 11 + 12 + 13);
81
82
  // 2. Put two tables to table cache and
83
1
  Reopen(options);
84
  // fetch key from 1st and 2nd table, which will internally place that table to
85
  // the table cache.
86
3
  for (int i = 0; i < 2; ++i) {
87
2
    Get(ToString(i * 100 + 0));
88
2
  }
89
90
1
  VerifyTableProperties(db_, 10 + 11 + 12 + 13);
91
92
  // 3. Put all tables to table cache
93
1
  Reopen(options);
94
  // fetch key from 1st and 2nd table, which will internally place that table to
95
  // the table cache.
96
5
  for (int i = 0; i < 4; ++i) {
97
4
    Get(ToString(i * 100 + 0));
98
4
  }
99
1
  VerifyTableProperties(db_, 10 + 11 + 12 + 13);
100
1
}
101
102
TablePropertiesCollection
103
DBTablePropertiesTest::TestGetPropertiesOfTablesInRange(
104
    std::vector<Range> ranges, std::size_t* num_properties,
105
0
    std::size_t* num_files) {
106
107
  // Since we deref zero element in the vector it can not be empty
108
  // otherwise we pass an address to some random memory
109
0
  EXPECT_GT(ranges.size(), 0U);
110
  // run the query
111
0
  TablePropertiesCollection props;
112
0
  EXPECT_OK(db_->GetPropertiesOfTablesInRange(
113
0
      db_->DefaultColumnFamily(), &ranges[0], ranges.size(), &props));
114
115
  // Make sure that we've received properties for those and for those files
116
  // only which fall within requested ranges
117
0
  std::vector<LiveFileMetaData> vmd;
118
0
  db_->GetLiveFilesMetaData(&vmd);
119
0
  for (auto& md : vmd) {
120
0
    std::string fn = md.db_path + md.name;
121
0
    bool in_range = false;
122
0
    for (auto& r : ranges) {
123
      // smallestkey < limit && largestkey >= start
124
0
      if (r.limit.compare(md.smallest.key) >= 0 &&
125
0
          r.start.compare(md.largest.key) <= 0) {
126
0
        in_range = true;
127
0
        EXPECT_GT(props.count(fn), 0);
128
0
      }
129
0
    }
130
0
    if (!in_range) {
131
0
      EXPECT_EQ(props.count(fn), 0);
132
0
    }
133
0
  }
134
135
0
  if (num_properties) {
136
0
    *num_properties = props.size();
137
0
  }
138
139
0
  if (num_files) {
140
0
    *num_files = vmd.size();
141
0
  }
142
0
  return props;
143
0
}
144
145
1
TEST_F(DBTablePropertiesTest, GetPropertiesOfTablesInRange) {
146
  // Fixed random sead
147
1
  Random rnd(301);
148
149
1
  Options options;
150
1
  options.create_if_missing = true;
151
1
  options.write_buffer_size = 4096;
152
1
  options.max_write_buffer_number = 8;
153
1
  options.level0_file_num_compaction_trigger = 2;
154
1
  options.level0_slowdown_writes_trigger = 2;
155
1
  options.level0_stop_writes_trigger = 4;
156
1
  options.target_file_size_base = 2048;
157
1
  options.max_bytes_for_level_base = 10240;
158
1
  options.max_bytes_for_level_multiplier = 4;
159
1
  options.soft_rate_limit = 1.1;
160
1
  options.num_levels = 8;
161
162
1
  DestroyAndReopen(options);
163
164
  // build a decent LSM
165
4.47k
  for (int i = 0; i < 10000; i++) {
166
4.47k
    ASSERT_OK(Put(test::RandomKey(&rnd, 5), RandomString(&rnd, 102)));
167
4.47k
  }
168
0
  ASSERT_OK(Flush());
169
0
  ASSERT_OK(db_->PauseBackgroundWork());
170
171
  // Ensure that we have at least L0, L1 and L2
172
0
  ASSERT_GT(NumTableFilesAtLevel(0), 0);
173
0
  ASSERT_GT(NumTableFilesAtLevel(1), 0);
174
0
  ASSERT_GT(NumTableFilesAtLevel(2), 0);
175
176
  // Query the largest range
177
0
  std::size_t num_properties, num_files;
178
0
  TestGetPropertiesOfTablesInRange(
179
0
      {Range(test::RandomKey(&rnd, 5, test::RandomKeyType::SMALLEST),
180
0
             test::RandomKey(&rnd, 5, test::RandomKeyType::LARGEST))},
181
0
      &num_properties, &num_files);
182
0
  ASSERT_EQ(num_properties, num_files);
183
184
  // Query the empty range
185
0
  TestGetPropertiesOfTablesInRange(
186
0
      {Range(test::RandomKey(&rnd, 5, test::RandomKeyType::LARGEST),
187
0
             test::RandomKey(&rnd, 5, test::RandomKeyType::SMALLEST))},
188
0
      &num_properties, &num_files);
189
0
  ASSERT_GT(num_files, 0);
190
0
  ASSERT_EQ(num_properties, 0);
191
192
  // Query the middle rangee
193
0
  TestGetPropertiesOfTablesInRange(
194
0
      {Range(test::RandomKey(&rnd, 5, test::RandomKeyType::MIDDLE),
195
0
             test::RandomKey(&rnd, 5, test::RandomKeyType::LARGEST))},
196
0
      &num_properties, &num_files);
197
0
  ASSERT_GT(num_files, 0);
198
0
  ASSERT_GT(num_files, num_properties);
199
0
  ASSERT_GT(num_properties, 0);
200
201
  // Query a bunch of random ranges
202
0
  for (int j = 0; j < 100; j++) {
203
    // create a bunch of ranges
204
0
    std::vector<std::string> random_keys;
205
    // Random returns numbers with zero included
206
    // when we pass empty ranges TestGetPropertiesOfTablesInRange()
207
    // derefs random memory in the empty ranges[0]
208
    // so want to be greater than zero and even since
209
    // the below loop requires that random_keys.size() to be even.
210
0
    auto n = 2 * (rnd.Uniform(50) + 1);
211
212
0
    for (uint32_t i = 0; i < n; ++i) {
213
0
      random_keys.push_back(test::RandomKey(&rnd, 5));
214
0
    }
215
216
0
    ASSERT_GT(random_keys.size(), 0U);
217
0
    ASSERT_EQ((random_keys.size() % 2), 0U);
218
219
0
    std::vector<Range> ranges;
220
0
    auto it = random_keys.begin();
221
0
    while (it != random_keys.end()) {
222
0
      ranges.push_back(Range(*it, *(it + 1)));
223
0
      it += 2;
224
0
    }
225
226
0
    TestGetPropertiesOfTablesInRange(std::move(ranges));
227
0
  }
228
0
}
229
}  // namespace rocksdb
230
231
#endif  // ROCKSDB_LITE
232
233
13.2k
int main(int argc, char** argv) {
234
13.2k
  rocksdb::port::InstallStackTraceHandler();
235
13.2k
  ::testing::InitGoogleTest(&argc, argv);
236
13.2k
  return RUN_ALL_TESTS();
237
13.2k
}