Coverage Report

Created: 2026-07-30 08:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/storage/data_dir.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 <gen_cpp/Types_types.h>
21
#include <stddef.h>
22
23
#include <atomic>
24
#include <condition_variable>
25
#include <cstdint>
26
#include <memory>
27
#include <mutex>
28
#include <optional>
29
#include <set>
30
#include <shared_mutex>
31
#include <string>
32
#include <string_view>
33
#include <vector>
34
35
#include "common/metrics/metrics.h"
36
#include "common/status.h"
37
#include "storage/olap_common.h"
38
39
namespace doris {
40
41
class Tablet;
42
class TabletManager;
43
class TxnManager;
44
class OlapMeta;
45
class RowsetIdGenerator;
46
class StorageEngine;
47
class DataDirSweepWorker;
48
enum class DataDirSweepJobType : uint8_t;
49
struct DataDirSweepJobResult;
50
51
struct RemoteGcStats {
52
    int64_t scanned = 0;
53
    std::optional<int64_t> backlog;
54
};
55
56
const char* const kTestFilePath = ".testfile";
57
58
// A DataDir used to manage data in same path.
59
// Now, After DataDir was created, it will never be deleted for easy implementation.
60
class DataDir {
61
public:
62
    DataDir(StorageEngine& engine, const std::string& path, int64_t capacity_bytes = -1,
63
            TStorageMedium::type storage_medium = TStorageMedium::HDD);
64
    ~DataDir();
65
66
    Status init(bool init_meta = true);
67
    void stop_bg_worker();
68
69
6.20M
    const std::string& path() const { return _path; }
70
450M
    size_t path_hash() const { return _path_hash; }
71
72
17.2M
    bool is_used() const { return _is_used; }
73
60
    int32_t cluster_id() const { return _cluster_id; }
74
60
    bool cluster_id_incomplete() const { return _cluster_id_incomplete; }
75
76
97
    DataDirInfo get_dir_info() {
77
97
        DataDirInfo info;
78
97
        info.path = _path;
79
97
        info.path_hash = _path_hash;
80
97
        info.disk_capacity = _disk_capacity_bytes;
81
97
        info.available = _available_bytes;
82
97
        info.trash_used_capacity = _trash_used_bytes.load(std::memory_order_relaxed);
83
97
        info.is_used = _is_used;
84
97
        info.storage_medium = _storage_medium;
85
97
        return info;
86
97
    }
87
88
    // save a cluster_id file under data path to prevent
89
    // invalid be config for example two be use the same
90
    // data path
91
    Status set_cluster_id(int32_t cluster_id);
92
    void health_check();
93
94
202
    int32_t get_shard() {
95
202
        return _current_shard.fetch_add(1, std::memory_order_relaxed) % MAX_SHARD_NUM;
96
202
    }
97
98
17.2k
    OlapMeta* get_meta() { return _meta; }
99
100
8.76k
    bool is_ssd_disk() const { return _storage_medium == TStorageMedium::SSD; }
101
102
1.27M
    TStorageMedium::type storage_medium() const { return _storage_medium; }
103
104
    void register_tablet(Tablet* tablet);
105
    void deregister_tablet(Tablet* tablet);
106
    void clear_tablets(std::vector<TabletInfo>* tablet_infos);
107
108
    std::string get_absolute_shard_path(int64_t shard_id);
109
    std::string get_absolute_tablet_path(int64_t shard_id, int64_t tablet_id, int32_t schema_hash);
110
111
    void find_tablet_in_trash(int64_t tablet_id, std::vector<std::string>* paths);
112
113
    static std::string get_root_path_from_schema_hash_path_in_trash(
114
            const std::string& schema_hash_dir_in_trash);
115
116
    // load data from meta and data files
117
    Status load();
118
119
    void perform_path_gc();
120
121
    Status perform_remote_rowset_gc(RemoteGcStats* stats = nullptr);
122
123
    Status perform_remote_tablet_gc(RemoteGcStats* stats = nullptr);
124
125
    // check if the capacity reach the limit after adding the incoming data
126
    // return true if limit reached, otherwise, return false.
127
    // TODO(cmy): for now we can not precisely calculate the capacity Doris used,
128
    // so in order to avoid running out of disk capacity, we currently use the actual
129
    // disk available capacity and total capacity to do the calculation.
130
    // So that the capacity Doris actually used may exceeds the user specified capacity.
131
    bool reach_capacity_limit(int64_t incoming_data_size);
132
133
    Status update_capacity();
134
135
    Status update_trash_capacity();
136
137
    void update_local_data_size(int64_t size);
138
139
    void update_remote_data_size(int64_t size);
140
141
    size_t tablet_size() const;
142
143
    void disks_compaction_score_increment(int64_t delta);
144
145
    void disks_compaction_num_increment(int64_t delta);
146
147
20.3k
    double get_usage(int64_t incoming_data_size) const {
148
20.3k
        return _disk_capacity_bytes == 0
149
20.3k
                       ? 0
150
20.3k
                       : (double)(_disk_capacity_bytes - _available_bytes + incoming_data_size) /
151
20.3k
                                 (double)_disk_capacity_bytes;
152
20.3k
    }
153
154
    // Move tablet to trash.
155
    Status move_to_trash(const std::string& tablet_path);
156
157
    static Status delete_tablet_parent_path_if_empty(const std::string& tablet_path);
158
159
private:
160
    friend class DataDirSweepWorker;
161
    friend class StorageEngine;
162
163
    Status _init_cluster_id();
164
    Status _init_capacity_and_create_shards();
165
    Status _init_meta();
166
167
    Status _check_disk();
168
    Status _read_and_write_test_file();
169
    // Check whether has old format (hdr_ start) in olap. When doris updating to current version,
170
    // it may lead to data missing. When conf::storage_strict_check_incompatible_old_format is true,
171
    // process will log fatal.
172
    Status _check_incompatible_old_format_tablet();
173
174
    int _path_gc_step {0};
175
176
    void _perform_tablet_gc(const std::string& tablet_schema_hash_path, int16_t shard_name);
177
178
    void _perform_rowset_gc(const std::string& tablet_schema_hash_path);
179
180
    Status _count_remote_gc_backlog(std::string_view prefix, int64_t* backlog);
181
182
    void _set_sweep_worker_running(bool running);
183
    void _set_sweep_worker_queue_depth(int64_t queue_depth);
184
    void _record_sweep_job_start(DataDirSweepJobType type);
185
    void _record_sweep_job_result(const DataDirSweepJobResult& result, bool job_started);
186
187
private:
188
    std::atomic<bool> _stop_bg_worker = false;
189
190
    StorageEngine& _engine;
191
    std::string _path;
192
    size_t _path_hash;
193
194
    // the actual available capacity of the disk of this data dir
195
    size_t _available_bytes;
196
    // the actual capacity of the disk of this data dir
197
    size_t _disk_capacity_bytes;
198
    std::atomic<int64_t> _trash_used_bytes {0};
199
    TStorageMedium::type _storage_medium;
200
    bool _is_used;
201
202
    int32_t _cluster_id;
203
    bool _cluster_id_incomplete = false;
204
    // This flag will be set true if this store was not in root path when reloading
205
    bool _to_be_deleted;
206
207
    static constexpr int32_t MAX_SHARD_NUM = 1024;
208
    std::atomic<int32_t> _current_shard {0};
209
    // used to protect and _tablet_set
210
    mutable std::mutex _mutex;
211
    std::set<TabletInfo> _tablet_set;
212
213
    OlapMeta* _meta = nullptr;
214
215
    std::shared_ptr<MetricEntity> _data_dir_metric_entity;
216
    IntGauge* disks_total_capacity = nullptr;
217
    IntGauge* disks_avail_capacity = nullptr;
218
    IntGauge* disks_local_used_capacity = nullptr;
219
    IntGauge* disks_remote_used_capacity = nullptr;
220
    IntGauge* disks_trash_used_capacity = nullptr;
221
    IntGauge* disks_state = nullptr;
222
    IntGauge* disks_compaction_score = nullptr;
223
    IntGauge* disks_compaction_num = nullptr;
224
    IntGauge* disks_sweep_worker_running = nullptr;
225
    IntGauge* disks_sweep_worker_queue_depth = nullptr;
226
    IntGauge* disks_sweep_worker_current_job = nullptr;
227
    IntCounter* disks_sweep_worker_completed_jobs = nullptr;
228
    IntCounter* disks_sweep_worker_failed_jobs = nullptr;
229
    IntGauge* disks_snapshot_sweep_last_duration_ms = nullptr;
230
    IntGauge* disks_trash_sweep_last_duration_ms = nullptr;
231
    IntGauge* disks_shutdown_tablet_sweep_last_duration_ms = nullptr;
232
    IntGauge* disks_remote_gc_last_duration_ms = nullptr;
233
    IntCounter* disks_remote_rowset_gc_scanned_total = nullptr;
234
    IntGauge* disks_remote_rowset_gc_backlog = nullptr;
235
    IntCounter* disks_remote_tablet_gc_scanned_total = nullptr;
236
    IntGauge* disks_remote_tablet_gc_backlog = nullptr;
237
    IntGauge* disks_trash_capacity_refresh_last_duration_ms = nullptr;
238
    IntGauge* disks_trash_capacity_refresh_last_success_time = nullptr;
239
    IntCounter* disks_trash_capacity_refresh_failed_total = nullptr;
240
};
241
242
} // namespace doris