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 | 1.04k | const std::string& path() const { return _path; } |
70 | 257 | size_t path_hash() const { return _path_hash; } |
71 | | |
72 | 725 | bool is_used() const { return _is_used; } |
73 | 52 | int32_t cluster_id() const { return _cluster_id; } |
74 | 52 | bool cluster_id_incomplete() const { return _cluster_id_incomplete; } |
75 | | |
76 | 6 | DataDirInfo get_dir_info() { |
77 | 6 | DataDirInfo info; |
78 | 6 | info.path = _path; |
79 | 6 | info.path_hash = _path_hash; |
80 | 6 | info.disk_capacity = _disk_capacity_bytes; |
81 | 6 | info.available = _available_bytes; |
82 | 6 | info.trash_used_capacity = _trash_used_bytes.load(std::memory_order_relaxed); |
83 | 6 | info.is_used = _is_used; |
84 | 6 | info.storage_medium = _storage_medium; |
85 | 6 | return info; |
86 | 6 | } |
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 | 3.29k | OlapMeta* get_meta() { return _meta; } |
99 | | |
100 | 0 | bool is_ssd_disk() const { return _storage_medium == TStorageMedium::SSD; } |
101 | | |
102 | 52 | 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 | 1.05k | double get_usage(int64_t incoming_data_size) const { |
148 | 1.05k | return _disk_capacity_bytes == 0 |
149 | 1.05k | ? 0 |
150 | 1.05k | : (double)(_disk_capacity_bytes - _available_bytes + incoming_data_size) / |
151 | 1.05k | (double)_disk_capacity_bytes; |
152 | 1.05k | } |
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 |