Coverage Report

Created: 2026-11-02 13:46

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