Coverage Report

Created: 2024-11-21 16:04

/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
    TabletSharedPtr find_best_tablet_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
4
    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
101
    // Extract tablet_id and schema_hash from given path.
102
    //
103
    // The normal path pattern is like "/data/{shard_id}/{tablet_id}/{schema_hash}/xxx.data".
104
    // Besides that, this also support empty tablet path, which path looks like
105
    // "/data/{shard_id}/{tablet_id}"
106
    //
107
    // Return true when the path matches the path pattern, and tablet_id and schema_hash is
108
    // saved in input params. When input path is an empty tablet directory, schema_hash will
109
    // be set to 0. Return false if the path don't match valid pattern.
110
    static bool get_tablet_id_and_schema_hash_from_path(const std::string& path,
111
                                                        TTabletId* tablet_id,
112
                                                        TSchemaHash* schema_hash);
113
114
    static bool get_rowset_id_from_path(const std::string& path, RowsetId* rowset_id);
115
116
    void get_tablet_stat(TTabletStatResult* result);
117
118
    // parse tablet header msg to generate tablet object
119
    // - restore: whether the request is from restore tablet action,
120
    //   where we should change tablet status from shutdown back to running
121
    Status load_tablet_from_meta(DataDir* data_dir, TTabletId tablet_id, TSchemaHash schema_hash,
122
                                 const std::string& header, bool update_meta, bool force = false,
123
                                 bool restore = false, bool check_path = true);
124
125
    Status load_tablet_from_dir(DataDir* data_dir, TTabletId tablet_id, SchemaHash schema_hash,
126
                                const std::string& schema_hash_path, bool force = false,
127
                                bool restore = false);
128
129
    // 获取所有tables的名字
130
    //
131
    // Return OK, if run ok
132
    //        Status::Error<INVALID_ARGUMENT>(), if tables is null
133
    Status report_tablet_info(TTabletInfo* tablet_info);
134
135
    void build_all_report_tablets_info(std::map<TTabletId, TTablet>* tablets_info);
136
137
    Status start_trash_sweep();
138
139
    void try_delete_unused_tablet_path(DataDir* data_dir, TTabletId tablet_id,
140
                                       SchemaHash schema_hash, const std::string& schema_hash_path,
141
                                       int16_t shard_id);
142
143
    void update_root_path_info(std::map<std::string, DataDirInfo>* path_map,
144
                               size_t* tablet_counter);
145
146
    void get_partition_related_tablets(int64_t partition_id, std::set<TabletInfo>* tablet_infos);
147
148
    void get_partitions_visible_version(std::map<int64_t, int64_t>* partitions_version);
149
150
    void update_partitions_visible_version(const std::map<int64_t, int64_t>& partitions_version);
151
152
    void do_tablet_meta_checkpoint(DataDir* data_dir);
153
154
    void obtain_specific_quantity_tablets(std::vector<TabletInfo>& tablets_info, int64_t num);
155
156
    // return `true` if register success
157
    Status register_transition_tablet(int64_t tablet_id, std::string reason);
158
    void unregister_transition_tablet(int64_t tablet_id, std::string reason);
159
160
    void get_tablets_distribution_on_different_disks(
161
            std::map<int64_t, std::map<DataDir*, int64_t>>& tablets_num_on_disk,
162
            std::map<int64_t, std::map<DataDir*, std::vector<TabletSize>>>& tablets_info_on_disk);
163
    void get_cooldown_tablets(std::vector<TabletSharedPtr>* tables,
164
                              std::vector<RowsetSharedPtr>* rowsets,
165
                              std::function<bool(const TabletSharedPtr&)> skip_tablet);
166
167
    void get_all_tablets_storage_format(TCheckStorageFormatResult* result);
168
169
    std::set<int64_t> check_all_tablet_segment(bool repair);
170
171
    bool update_tablet_partition_id(::doris::TPartitionId partition_id,
172
                                    ::doris::TTabletId tablet_id);
173
174
private:
175
    // Add a tablet pointer to StorageEngine
176
    // If force, drop the existing tablet add this new one
177
    //
178
    // Return OK, if run ok
179
    //        OLAP_ERR_TABLE_INSERT_DUPLICATION_ERROR, if find duplication
180
    //        Status::Error<UNINITIALIZED>(), if not inited
181
    Status _add_tablet_unlocked(TTabletId tablet_id, const TabletSharedPtr& tablet,
182
                                bool update_meta, bool force, RuntimeProfile* profile);
183
184
    Status _add_tablet_to_map_unlocked(TTabletId tablet_id, const TabletSharedPtr& tablet,
185
                                       bool update_meta, bool keep_files, bool drop_old,
186
                                       RuntimeProfile* profile);
187
188
    bool _check_tablet_id_exist_unlocked(TTabletId tablet_id);
189
190
    Status _drop_tablet_unlocked(TTabletId tablet_id, TReplicaId replica_id, bool keep_files,
191
                                 bool is_drop_table_or_partition);
192
193
    TabletSharedPtr _get_tablet_unlocked(TTabletId tablet_id);
194
    TabletSharedPtr _get_tablet_unlocked(TTabletId tablet_id, bool include_deleted,
195
                                         std::string* err);
196
197
    TabletSharedPtr _internal_create_tablet_unlocked(const TCreateTabletReq& request,
198
                                                     const bool is_schema_change,
199
                                                     const Tablet* base_tablet,
200
                                                     const std::vector<DataDir*>& data_dirs,
201
                                                     RuntimeProfile* profile);
202
    TabletSharedPtr _create_tablet_meta_and_dir_unlocked(const TCreateTabletReq& request,
203
                                                         const bool is_schema_change,
204
                                                         const Tablet* base_tablet,
205
                                                         const std::vector<DataDir*>& data_dirs,
206
                                                         RuntimeProfile* profile);
207
    Status _create_tablet_meta_unlocked(const TCreateTabletReq& request, DataDir* store,
208
                                        const bool is_schema_change_tablet,
209
                                        const Tablet* base_tablet,
210
                                        TabletMetaSharedPtr* tablet_meta);
211
212
    void _add_tablet_to_partition(const TabletSharedPtr& tablet);
213
214
    void _remove_tablet_from_partition(const TabletSharedPtr& tablet);
215
216
    std::shared_mutex& _get_tablets_shard_lock(TTabletId tabletId);
217
218
    bool _move_tablet_to_trash(const TabletSharedPtr& tablet);
219
220
private:
221
    DISALLOW_COPY_AND_ASSIGN(TabletManager);
222
223
    using tablet_map_t = std::unordered_map<int64_t, TabletSharedPtr>;
224
225
    struct tablets_shard {
226
628
        tablets_shard() = default;
227
0
        tablets_shard(tablets_shard&& shard) {
228
0
            tablet_map = std::move(shard.tablet_map);
229
0
            tablets_under_transition = std::move(shard.tablets_under_transition);
230
0
        }
231
        mutable std::shared_mutex lock;
232
        tablet_map_t tablet_map;
233
        std::mutex lock_for_transition;
234
        // tablet do clone, path gc, move to trash, disk migrate will record in tablets_under_transition
235
        // tablet <reason, thread_id, lock_times>
236
        std::map<int64_t, std::tuple<std::string, std::thread::id, int64_t>>
237
                tablets_under_transition;
238
    };
239
240
    struct Partition {
241
        std::set<TabletInfo> tablets;
242
        std::shared_ptr<VersionWithTime> visible_version {new VersionWithTime};
243
    };
244
245
    StorageEngine& _engine;
246
247
    // TODO: memory size of TabletSchema cannot be accurately tracked.
248
    std::shared_ptr<MemTracker> _tablet_meta_mem_tracker;
249
250
    const int32_t _tablets_shards_size;
251
    const int32_t _tablets_shards_mask;
252
    std::vector<tablets_shard> _tablets_shards;
253
254
    // Protect _partitions, should not be obtained before _tablet_map_lock to avoid dead lock
255
    std::shared_mutex _partitions_lock;
256
    // partition_id => partition
257
    std::map<int64_t, Partition> _partitions;
258
259
    // Protect _shutdown_tablets, should not be obtained before _tablet_map_lock to avoid dead lock
260
    std::shared_mutex _shutdown_tablets_lock;
261
    // the delete tablets. notice only allow function `start_trash_sweep` can erase tablets in _shutdown_tablets
262
    std::list<TabletSharedPtr> _shutdown_tablets;
263
    std::mutex _gc_tablets_lock;
264
265
    std::mutex _tablet_stat_cache_mutex;
266
    std::shared_ptr<std::vector<TTabletStat>> _tablet_stat_list_cache =
267
            std::make_shared<std::vector<TTabletStat>>();
268
269
    tablet_map_t& _get_tablet_map(TTabletId tablet_id);
270
271
    tablets_shard& _get_tablets_shard(TTabletId tabletId);
272
273
    std::mutex _two_tablet_mtx;
274
};
275
276
} // namespace doris