Coverage Report

Created: 2026-11-03 20:28

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