YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/rocksdb/db/file_indexer.h
Line
Count
Source
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
#ifndef YB_ROCKSDB_DB_FILE_INDEXER_H
25
#define YB_ROCKSDB_DB_FILE_INDEXER_H
26
27
#pragma once
28
29
#include <functional>
30
#include <limits>
31
#include <vector>
32
33
#include "yb/rocksdb/port/port.h"
34
#include "yb/rocksdb/util/arena.h"
35
#include "yb/rocksdb/util/autovector.h"
36
37
namespace rocksdb {
38
39
class Comparator;
40
struct FileMetaData;
41
struct FileLevel;
42
43
// The file tree structure in Version is prebuilt and the range of each file
44
// is known. On Version::Get(), it uses binary search to find a potential file
45
// and then check if a target key can be found in the file by comparing the key
46
// to each file's smallest and largest key. The results of these comparisons
47
// can be reused beyond checking if a key falls into a file's range.
48
// With some pre-calculated knowledge, each key comparison that has been done
49
// can serve as a hint to narrow down further searches: if a key compared to
50
// be smaller than a file's smallest or largest, that comparison can be used
51
// to find out the right bound of next binary search. Similarly, if a key
52
// compared to be larger than a file's smallest or largest, it can be utilized
53
// to find out the left bound of next binary search.
54
// With these hints: it can greatly reduce the range of binary search,
55
// especially for bottom levels, given that one file most likely overlaps with
56
// only N files from level below (where N is max_bytes_for_level_multiplier).
57
// So on level L, we will only look at ~N files instead of N^L files on the
58
// naive approach.
59
class FileIndexer {
60
 public:
61
  explicit FileIndexer(const Comparator* ucmp);
62
63
  size_t NumLevelIndex() const;
64
65
  size_t LevelIndexSize(size_t level) const;
66
67
  // Return a file index range in the next level to search for a key based on
68
  // smallest and largest key comparison for the current file specified by
69
  // level and file_index. When *left_index < *right_index, both index should
70
  // be valid and fit in the vector size.
71
  void GetNextLevelIndex(const size_t level, const size_t file_index,
72
                         const int cmp_smallest, const int cmp_largest,
73
                         int32_t* left_bound, int32_t* right_bound) const;
74
75
  void UpdateIndex(Arena* arena, const size_t num_levels,
76
                   std::vector<FileMetaData*>* const files);
77
78
  enum {
79
    // MSVC version 1800 still does not have constexpr for ::max()
80
    kLevelMaxIndex = rocksdb::port::kMaxInt32
81
  };
82
83
 private:
84
  size_t num_levels_;
85
  const Comparator* ucmp_;
86
87
  struct IndexUnit {
88
    IndexUnit()
89
249k
      : smallest_lb(0), largest_lb(0), smallest_rb(-1), largest_rb(-1) {}
90
    // During file search, a key is compared against smallest and largest
91
    // from a FileMetaData. It can have 3 possible outcomes:
92
    // (1) key is smaller than smallest, implying it is also smaller than
93
    //     larger. Precalculated index based on "smallest < smallest" can
94
    //     be used to provide right bound.
95
    // (2) key is in between smallest and largest.
96
    //     Precalculated index based on "smallest > greatest" can be used to
97
    //     provide left bound.
98
    //     Precalculated index based on "largest < smallest" can be used to
99
    //     provide right bound.
100
    // (3) key is larger than largest, implying it is also larger than smallest.
101
    //     Precalculated index based on "largest > largest" can be used to
102
    //     provide left bound.
103
    //
104
    // As a result, we will need to do:
105
    // Compare smallest (<=) and largest keys from upper level file with
106
    // smallest key from lower level to get a right bound.
107
    // Compare smallest (>=) and largest keys from upper level file with
108
    // largest key from lower level to get a left bound.
109
    //
110
    // Example:
111
    //    level 1:              [50 - 60]
112
    //    level 2:        [1 - 40], [45 - 55], [58 - 80]
113
    // A key 35, compared to be less than 50, 3rd file on level 2 can be
114
    // skipped according to rule (1). LB = 0, RB = 1.
115
    // A key 53, sits in the middle 50 and 60. 1st file on level 2 can be
116
    // skipped according to rule (2)-a, but the 3rd file cannot be skipped
117
    // because 60 is greater than 58. LB = 1, RB = 2.
118
    // A key 70, compared to be larger than 60. 1st and 2nd file can be skipped
119
    // according to rule (3). LB = 2, RB = 2.
120
    //
121
    // Point to a left most file in a lower level that may contain a key,
122
    // which compares greater than smallest of a FileMetaData (upper level)
123
    int32_t smallest_lb;
124
    // Point to a left most file in a lower level that may contain a key,
125
    // which compares greater than largest of a FileMetaData (upper level)
126
    int32_t largest_lb;
127
    // Point to a right most file in a lower level that may contain a key,
128
    // which compares smaller than smallest of a FileMetaData (upper level)
129
    int32_t smallest_rb;
130
    // Point to a right most file in a lower level that may contain a key,
131
    // which compares smaller than largest of a FileMetaData (upper level)
132
    int32_t largest_rb;
133
  };
134
135
  // Data structure to store IndexUnits in a whole level
136
  struct IndexLevel {
137
    size_t num_index;
138
    IndexUnit* index_units;
139
140
10.7M
    IndexLevel() : num_index(0), index_units(nullptr) {}
141
  };
142
143
  void CalculateLB(
144
      const std::vector<FileMetaData*>& upper_files,
145
      const std::vector<FileMetaData*>& lower_files, IndexLevel* index_level,
146
      std::function<int(const FileMetaData*, const FileMetaData*)> cmp_op,
147
      std::function<void(IndexUnit*, int32_t)> set_index);
148
149
  void CalculateRB(
150
      const std::vector<FileMetaData*>& upper_files,
151
      const std::vector<FileMetaData*>& lower_files, IndexLevel* index_level,
152
      std::function<int(const FileMetaData*, const FileMetaData*)> cmp_op,
153
      std::function<void(IndexUnit*, int32_t)> set_index);
154
155
  autovector<IndexLevel> next_level_index_;
156
  int32_t* level_rb_;
157
};
158
159
}  // namespace rocksdb
160
161
#endif // YB_ROCKSDB_DB_FILE_INDEXER_H