Coverage Report

Created: 2025-07-25 10:29

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