Coverage Report

Created: 2024-11-20 12:06

/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