/root/doris/be/src/olap/tablet_manager.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | #pragma once |
19 | | |
20 | | #include <butil/macros.h> |
21 | | #include <gen_cpp/BackendService_types.h> |
22 | | #include <gen_cpp/Types_types.h> |
23 | | #include <stddef.h> |
24 | | #include <stdint.h> |
25 | | |
26 | | #include <functional> |
27 | | #include <map> |
28 | | #include <memory> |
29 | | #include <mutex> |
30 | | #include <set> |
31 | | #include <shared_mutex> |
32 | | #include <string> |
33 | | #include <string_view> |
34 | | #include <unordered_map> |
35 | | #include <unordered_set> |
36 | | #include <utility> |
37 | | #include <vector> |
38 | | |
39 | | #include "common/status.h" |
40 | | #include "olap/olap_common.h" |
41 | | #include "olap/tablet.h" |
42 | | #include "olap/tablet_meta.h" |
43 | | |
44 | | namespace doris { |
45 | | |
46 | | class DataDir; |
47 | | class CumulativeCompactionPolicy; |
48 | | class MemTracker; |
49 | | class TCreateTabletReq; |
50 | | class TTablet; |
51 | | class TTabletInfo; |
52 | | |
53 | | // TabletManager provides get, add, delete tablet method for storage engine |
54 | | // NOTE: If you want to add a method that needs to hold meta-lock before you can call it, |
55 | | // please uniformly name the method in "xxx_unlocked()" mode |
56 | | class TabletManager { |
57 | | public: |
58 | | TabletManager(StorageEngine& engine, int32_t tablet_map_lock_shard_size); |
59 | | ~TabletManager(); |
60 | | |
61 | | bool check_tablet_id_exist(TTabletId tablet_id); |
62 | | |
63 | | // The param stores holds all candidate data_dirs for this tablet. |
64 | | // NOTE: If the request is from a schema-changing tablet, The directory selected by the |
65 | | // new tablet should be the same as the directory of origin tablet. Because the |
66 | | // linked-schema-change type requires Linux hard-link, which does not support cross disk. |
67 | | // TODO(lingbin): Other schema-change type do not need to be on the same disk. Because |
68 | | // there may be insufficient space on the current disk, which will lead the schema-change |
69 | | // task to be fail, even if there is enough space on other disks |
70 | | Status create_tablet(const TCreateTabletReq& request, std::vector<DataDir*> stores, |
71 | | RuntimeProfile* profile); |
72 | | |
73 | | // Drop a tablet by description. |
74 | | // If `is_drop_table_or_partition` is true, we need to remove all remote rowsets in this tablet. |
75 | | Status drop_tablet(TTabletId tablet_id, TReplicaId replica_id, bool is_drop_table_or_partition); |
76 | | |
77 | | // Find two tablets. |
78 | | // One with the highest score to execute single compaction, |
79 | | // the other with the highest score to execute cumu or base compaction. |
80 | | // Single compaction needs to be completed successfully after the peer completes it. |
81 | | // We need to generate two types of tasks separately to avoid continuously generating |
82 | | // single compaction tasks for the tablet. |
83 | | std::vector<TabletSharedPtr> find_best_tablets_to_compaction( |
84 | | CompactionType compaction_type, DataDir* data_dir, |
85 | | const std::unordered_set<TabletSharedPtr>& tablet_submitted_compaction, uint32_t* score, |
86 | | const std::unordered_map<std::string_view, std::shared_ptr<CumulativeCompactionPolicy>>& |
87 | | all_cumulative_compaction_policies); |
88 | | |
89 | | TabletSharedPtr get_tablet(TTabletId tablet_id, bool include_deleted = false, |
90 | | std::string* err = nullptr); |
91 | | |
92 | | TabletSharedPtr get_tablet(TTabletId tablet_id, TabletUid tablet_uid, |
93 | | bool include_deleted = false, std::string* err = nullptr); |
94 | | |
95 | | std::vector<TabletSharedPtr> get_all_tablet( |
96 | | std::function<bool(Tablet*)>&& filter = filter_used_tablets); |
97 | | |
98 | | // Handler not hold the shard lock. |
99 | | void for_each_tablet(std::function<void(const TabletSharedPtr&)>&& handler, |
100 | | std::function<bool(Tablet*)>&& filter = filter_used_tablets); |
101 | | |
102 | 52 | static bool filter_all_tablets(Tablet* tablet) { return true; } |
103 | 0 | static bool filter_used_tablets(Tablet* tablet) { return tablet->is_used(); } |
104 | | |
105 | | uint64_t get_rowset_nums(); |
106 | | uint64_t get_segment_nums(); |
107 | | |
108 | | // Extract tablet_id and schema_hash from given path. |
109 | | // |
110 | | // The normal path pattern is like "/data/{shard_id}/{tablet_id}/{schema_hash}/xxx.data". |
111 | | // Besides that, this also support empty tablet path, which path looks like |
112 | | // "/data/{shard_id}/{tablet_id}" |
113 | | // |
114 | | // Return true when the path matches the path pattern, and tablet_id and schema_hash is |
115 | | // saved in input params. When input path is an empty tablet directory, schema_hash will |
116 | | // be set to 0. Return false if the path don't match valid pattern. |
117 | | static bool get_tablet_id_and_schema_hash_from_path(const std::string& path, |
118 | | TTabletId* tablet_id, |
119 | | TSchemaHash* schema_hash); |
120 | | |
121 | | static bool get_rowset_id_from_path(const std::string& path, RowsetId* rowset_id); |
122 | | |
123 | | void get_tablet_stat(TTabletStatResult* result); |
124 | | |
125 | | // parse tablet header msg to generate tablet object |
126 | | // - restore: whether the request is from restore tablet action, |
127 | | // where we should change tablet status from shutdown back to running |
128 | | Status load_tablet_from_meta(DataDir* data_dir, TTabletId tablet_id, TSchemaHash schema_hash, |
129 | | std::string_view header, bool update_meta, bool force = false, |
130 | | bool restore = false, bool check_path = true); |
131 | | |
132 | | Status load_tablet_from_dir(DataDir* data_dir, TTabletId tablet_id, SchemaHash schema_hash, |
133 | | const std::string& schema_hash_path, bool force = false, |
134 | | bool restore = false); |
135 | | |
136 | | // 获取所有tables的名字 |
137 | | // |
138 | | // Return OK, if run ok |
139 | | // Status::Error<INVALID_ARGUMENT>(), if tables is null |
140 | | Status report_tablet_info(TTabletInfo* tablet_info); |
141 | | |
142 | | void build_all_report_tablets_info(std::map<TTabletId, TTablet>* tablets_info); |
143 | | |
144 | | Status start_trash_sweep(); |
145 | | |
146 | | void try_delete_unused_tablet_path(DataDir* data_dir, TTabletId tablet_id, |
147 | | SchemaHash schema_hash, const std::string& schema_hash_path, |
148 | | int16_t shard_id); |
149 | | |
150 | | void update_root_path_info(std::map<std::string, DataDirInfo>* path_map, |
151 | | size_t* tablet_counter); |
152 | | |
153 | | void get_partition_related_tablets(int64_t partition_id, std::set<TabletInfo>* tablet_infos); |
154 | | |
155 | | void get_partitions_visible_version(std::map<int64_t, int64_t>* partitions_version); |
156 | | |
157 | | void update_partitions_visible_version(const std::map<int64_t, int64_t>& partitions_version); |
158 | | |
159 | | void do_tablet_meta_checkpoint(DataDir* data_dir); |
160 | | |
161 | | void obtain_specific_quantity_tablets(std::vector<TabletInfo>& tablets_info, int64_t num); |
162 | | |
163 | | // return `true` if register success |
164 | | Status register_transition_tablet(int64_t tablet_id, std::string reason); |
165 | | void unregister_transition_tablet(int64_t tablet_id, std::string reason); |
166 | | |
167 | | void get_tablets_distribution_on_different_disks( |
168 | | std::map<int64_t, std::map<DataDir*, int64_t>>& tablets_num_on_disk, |
169 | | std::map<int64_t, std::map<DataDir*, std::vector<TabletSize>>>& tablets_info_on_disk); |
170 | | void get_cooldown_tablets(std::vector<TabletSharedPtr>* tables, |
171 | | std::vector<RowsetSharedPtr>* rowsets, |
172 | | std::function<bool(const TabletSharedPtr&)> skip_tablet); |
173 | | |
174 | | void get_all_tablets_storage_format(TCheckStorageFormatResult* result); |
175 | | |
176 | | std::set<int64_t> check_all_tablet_segment(bool repair); |
177 | | |
178 | | bool update_tablet_partition_id(::doris::TPartitionId partition_id, |
179 | | ::doris::TTabletId tablet_id); |
180 | | |
181 | | private: |
182 | | // Add a tablet pointer to StorageEngine |
183 | | // If force, drop the existing tablet add this new one |
184 | | // |
185 | | // Return OK, if run ok |
186 | | // OLAP_ERR_TABLE_INSERT_DUPLICATION_ERROR, if find duplication |
187 | | // Status::Error<UNINITIALIZED>(), if not inited |
188 | | Status _add_tablet_unlocked(TTabletId tablet_id, const TabletSharedPtr& tablet, |
189 | | bool update_meta, bool force, RuntimeProfile* profile); |
190 | | |
191 | | Status _add_tablet_to_map_unlocked(TTabletId tablet_id, const TabletSharedPtr& tablet, |
192 | | bool update_meta, bool keep_files, bool drop_old, |
193 | | RuntimeProfile* profile); |
194 | | |
195 | | bool _check_tablet_id_exist_unlocked(TTabletId tablet_id); |
196 | | |
197 | | Status _drop_tablet(TTabletId tablet_id, TReplicaId replica_id, bool keep_files, |
198 | | bool is_drop_table_or_partition, bool had_held_shard_lock); |
199 | | |
200 | | TabletSharedPtr _get_tablet_unlocked(TTabletId tablet_id); |
201 | | TabletSharedPtr _get_tablet_unlocked(TTabletId tablet_id, bool include_deleted, |
202 | | std::string* err); |
203 | | |
204 | | TabletSharedPtr _internal_create_tablet_unlocked(const TCreateTabletReq& request, |
205 | | const bool is_schema_change, |
206 | | const Tablet* base_tablet, |
207 | | const std::vector<DataDir*>& data_dirs, |
208 | | RuntimeProfile* profile); |
209 | | TabletSharedPtr _create_tablet_meta_and_dir_unlocked(const TCreateTabletReq& request, |
210 | | const bool is_schema_change, |
211 | | const Tablet* base_tablet, |
212 | | const std::vector<DataDir*>& data_dirs, |
213 | | RuntimeProfile* profile); |
214 | | Status _create_tablet_meta_unlocked(const TCreateTabletReq& request, DataDir* store, |
215 | | const bool is_schema_change_tablet, |
216 | | const Tablet* base_tablet, |
217 | | TabletMetaSharedPtr* tablet_meta); |
218 | | |
219 | | void _add_tablet_to_partition(const TabletSharedPtr& tablet); |
220 | | |
221 | | void _remove_tablet_from_partition(const TabletSharedPtr& tablet); |
222 | | |
223 | | std::shared_mutex& _get_tablets_shard_lock(TTabletId tabletId); |
224 | | |
225 | | bool _move_tablet_to_trash(const TabletSharedPtr& tablet); |
226 | | |
227 | | private: |
228 | | DISALLOW_COPY_AND_ASSIGN(TabletManager); |
229 | | |
230 | | using tablet_map_t = std::unordered_map<int64_t, TabletSharedPtr>; |
231 | | |
232 | | struct tablets_shard { |
233 | 660 | tablets_shard() = default; |
234 | 0 | tablets_shard(tablets_shard&& shard) { |
235 | 0 | tablet_map = std::move(shard.tablet_map); |
236 | 0 | tablets_under_transition = std::move(shard.tablets_under_transition); |
237 | 0 | } |
238 | | mutable std::shared_mutex lock; |
239 | | tablet_map_t tablet_map; |
240 | | std::mutex lock_for_transition; |
241 | | // tablet do clone, path gc, move to trash, disk migrate will record in tablets_under_transition |
242 | | // tablet <reason, thread_id, lock_times> |
243 | | std::map<int64_t, std::tuple<std::string, std::thread::id, int64_t>> |
244 | | tablets_under_transition; |
245 | | }; |
246 | | |
247 | | struct Partition { |
248 | | std::set<TabletInfo> tablets; |
249 | | std::shared_ptr<VersionWithTime> visible_version {new VersionWithTime}; |
250 | | }; |
251 | | |
252 | | StorageEngine& _engine; |
253 | | |
254 | | // TODO: memory size of TabletSchema cannot be accurately tracked. |
255 | | std::shared_ptr<MemTracker> _tablet_meta_mem_tracker; |
256 | | |
257 | | const int32_t _tablets_shards_size; |
258 | | const int32_t _tablets_shards_mask; |
259 | | std::vector<tablets_shard> _tablets_shards; |
260 | | |
261 | | // Protect _partitions, should not be obtained before _tablet_map_lock to avoid dead lock |
262 | | std::shared_mutex _partitions_lock; |
263 | | // partition_id => partition |
264 | | std::map<int64_t, Partition> _partitions; |
265 | | |
266 | | // Protect _shutdown_tablets, should not be obtained before _tablet_map_lock to avoid dead lock |
267 | | std::shared_mutex _shutdown_tablets_lock; |
268 | | // the delete tablets. notice only allow function `start_trash_sweep` can erase tablets in _shutdown_tablets |
269 | | std::list<TabletSharedPtr> _shutdown_tablets; |
270 | | std::mutex _gc_tablets_lock; |
271 | | |
272 | | std::mutex _tablet_stat_cache_mutex; |
273 | | std::shared_ptr<std::vector<TTabletStat>> _tablet_stat_list_cache = |
274 | | std::make_shared<std::vector<TTabletStat>>(); |
275 | | |
276 | | tablet_map_t& _get_tablet_map(TTabletId tablet_id); |
277 | | |
278 | | tablets_shard& _get_tablets_shard(TTabletId tabletId); |
279 | | |
280 | | std::mutex _two_tablet_mtx; |
281 | | }; |
282 | | |
283 | | } // namespace doris |