Coverage Report

Created: 2026-03-14 18:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/storage/rowset/rowset_meta.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
#ifndef DORIS_BE_SRC_OLAP_ROWSET_ROWSET_META_H
19
#define DORIS_BE_SRC_OLAP_ROWSET_ROWSET_META_H
20
21
#include <gen_cpp/olap_file.pb.h>
22
#include <glog/logging.h>
23
24
#include <atomic>
25
#include <chrono>
26
#include <cstdint>
27
#include <memory>
28
#include <string>
29
#include <vector>
30
31
#include "common/cast_set.h"
32
#include "common/config.h"
33
#include "common/status.h"
34
#include "io/fs/encrypted_fs_factory.h"
35
#include "io/fs/file_system.h"
36
#include "runtime/memory/lru_cache_policy.h"
37
#include "storage/metadata_adder.h"
38
#include "storage/olap_common.h"
39
#include "storage/rowset/rowset_fwd.h"
40
#include "storage/storage_policy.h"
41
#include "storage/tablet/tablet_fwd.h"
42
#include "util/once.h"
43
44
namespace doris {
45
46
#include "common/compile_check_begin.h"
47
48
class RowsetMeta : public MetadataAdder<RowsetMeta> {
49
public:
50
1.17M
    RowsetMeta() = default;
51
    ~RowsetMeta();
52
53
    bool init(std::string_view pb_rowset_meta);
54
55
    bool init(const RowsetMeta* rowset_meta);
56
57
    bool init_from_pb(const RowsetMetaPB& rowset_meta_pb);
58
59
    bool init_from_json(const std::string& json_rowset_meta);
60
61
0
    bool serialize(std::string* value) { return _serialize_to_pb(value); }
62
63
    bool json_rowset_meta(std::string* json_rowset_meta);
64
65
    // If the rowset is a local rowset, return the global local file system.
66
    // Otherwise, return the remote file system corresponding to rowset's resource id.
67
    // Note that if the resource id cannot be found for the corresponding remote file system, nullptr will be returned.
68
    MOCK_FUNCTION io::FileSystemSPtr fs();
69
70
    io::FileSystemSPtr physical_fs();
71
72
    Result<const StorageResource*> remote_storage_resource();
73
74
    void set_remote_storage_resource(StorageResource resource);
75
76
239k
    const std::string& resource_id() const { return _rowset_meta_pb.resource_id(); }
77
78
130k
    void set_resource_id(const std::string& resource_id) {
79
130k
        _rowset_meta_pb.set_resource_id(resource_id);
80
130k
    }
81
82
47.7M
    bool is_local() const { return !_rowset_meta_pb.has_resource_id(); }
83
84
    bool has_variant_type_in_schema() const;
85
86
24.3M
    RowsetId rowset_id() const { return _rowset_id; }
87
88
346k
    void set_rowset_id(const RowsetId& rowset_id) {
89
        // rowset id is a required field, just set it to 0
90
346k
        _rowset_meta_pb.set_rowset_id(0);
91
346k
        _rowset_id = rowset_id;
92
346k
        _rowset_meta_pb.set_rowset_id_v2(rowset_id.to_string());
93
346k
    }
94
95
8.97M
    int64_t tablet_id() const { return _rowset_meta_pb.tablet_id(); }
96
97
346k
    void set_tablet_id(int64_t tablet_id) { _rowset_meta_pb.set_tablet_id(tablet_id); }
98
99
    int64_t index_id() const { return _rowset_meta_pb.index_id(); }
100
101
334k
    void set_index_id(int64_t index_id) { _rowset_meta_pb.set_index_id(index_id); }
102
103
1.52k
    TabletUid tablet_uid() const { return _rowset_meta_pb.tablet_uid(); }
104
105
142k
    void set_tablet_uid(TabletUid tablet_uid) {
106
142k
        *(_rowset_meta_pb.mutable_tablet_uid()) = tablet_uid.to_proto();
107
142k
    }
108
109
300k
    int64_t txn_id() const { return _rowset_meta_pb.txn_id(); }
110
111
333k
    void set_txn_id(int64_t txn_id) { _rowset_meta_pb.set_txn_id(txn_id); }
112
113
130k
    int32_t tablet_schema_hash() const { return _rowset_meta_pb.tablet_schema_hash(); }
114
115
335k
    void set_tablet_schema_hash(int32_t tablet_schema_hash) {
116
335k
        _rowset_meta_pb.set_tablet_schema_hash(tablet_schema_hash);
117
335k
    }
118
119
2.43M
    RowsetTypePB rowset_type() const { return _rowset_meta_pb.rowset_type(); }
120
121
337k
    void set_rowset_type(RowsetTypePB rowset_type) { _rowset_meta_pb.set_rowset_type(rowset_type); }
122
123
680k
    RowsetStatePB rowset_state() const { return _rowset_meta_pb.rowset_state(); }
124
125
543k
    void set_rowset_state(RowsetStatePB rowset_state) {
126
543k
        _rowset_meta_pb.set_rowset_state(rowset_state);
127
543k
    }
128
129
49.1M
    Version version() const {
130
49.1M
        return {_rowset_meta_pb.start_version(), _rowset_meta_pb.end_version()};
131
49.1M
    }
132
133
185k
    void set_version(Version version) {
134
185k
        _rowset_meta_pb.set_start_version(version.first);
135
185k
        _rowset_meta_pb.set_end_version(version.second);
136
185k
    }
137
138
1.16M
    bool has_version() const {
139
1.16M
        return _rowset_meta_pb.has_start_version() && _rowset_meta_pb.has_end_version();
140
1.16M
    }
141
142
5.02M
    int64_t start_version() const { return _rowset_meta_pb.start_version(); }
143
144
5.30M
    int64_t end_version() const { return _rowset_meta_pb.end_version(); }
145
146
9.26M
    int64_t num_rows() const { return _rowset_meta_pb.num_rows(); }
147
148
360k
    void set_num_rows(int64_t num_rows) { _rowset_meta_pb.set_num_rows(num_rows); }
149
150
228k
    void set_num_segment_rows(const std::vector<uint32_t>& num_segment_rows) {
151
228k
        _rowset_meta_pb.mutable_num_segment_rows()->Assign(num_segment_rows.cbegin(),
152
228k
                                                           num_segment_rows.cend());
153
228k
    }
154
155
86
    void get_num_segment_rows(std::vector<uint32_t>* num_segment_rows) const {
156
86
        num_segment_rows->assign(_rowset_meta_pb.num_segment_rows().cbegin(),
157
86
                                 _rowset_meta_pb.num_segment_rows().cend());
158
86
    }
159
160
154k
    auto& get_num_segment_rows() const { return _rowset_meta_pb.num_segment_rows(); }
161
162
10.0M
    int64_t total_disk_size() const { return _rowset_meta_pb.total_disk_size(); }
163
164
368k
    void set_total_disk_size(int64_t total_disk_size) {
165
368k
        _rowset_meta_pb.set_total_disk_size(total_disk_size);
166
368k
    }
167
168
9.10M
    int64_t data_disk_size() const { return _rowset_meta_pb.data_disk_size(); }
169
170
360k
    void set_data_disk_size(int64_t data_disk_size) {
171
360k
        _rowset_meta_pb.set_data_disk_size(data_disk_size);
172
360k
    }
173
174
2.32M
    int64_t index_disk_size() const { return _rowset_meta_pb.index_disk_size(); }
175
176
359k
    void set_index_disk_size(int64_t index_disk_size) {
177
359k
        _rowset_meta_pb.set_index_disk_size(index_disk_size);
178
359k
    }
179
180
0
    void zone_maps(std::vector<ZoneMap>* zone_maps) {
181
0
        for (const ZoneMap& zone_map : _rowset_meta_pb.zone_maps()) {
182
0
            zone_maps->push_back(zone_map);
183
0
        }
184
0
    }
185
186
0
    void set_zone_maps(const std::vector<ZoneMap>& zone_maps) {
187
0
        for (const ZoneMap& zone_map : zone_maps) {
188
0
            ZoneMap* new_zone_map = _rowset_meta_pb.add_zone_maps();
189
0
            *new_zone_map = zone_map;
190
0
        }
191
0
    }
192
193
0
    void add_zone_map(const ZoneMap& zone_map) {
194
0
        ZoneMap* new_zone_map = _rowset_meta_pb.add_zone_maps();
195
0
        *new_zone_map = zone_map;
196
0
    }
197
198
5.33M
    bool has_delete_predicate() const { return _rowset_meta_pb.has_delete_predicate(); }
199
200
8.22k
    const DeletePredicatePB& delete_predicate() const { return _rowset_meta_pb.delete_predicate(); }
201
202
0
    DeletePredicatePB* mutable_delete_predicate() {
203
0
        return _rowset_meta_pb.mutable_delete_predicate();
204
0
    }
205
206
3.26k
    void set_delete_predicate(DeletePredicatePB delete_predicate) {
207
3.26k
        DeletePredicatePB* new_delete_condition = _rowset_meta_pb.mutable_delete_predicate();
208
3.26k
        *new_delete_condition = std::move(delete_predicate);
209
3.26k
    }
210
211
8.77k
    bool empty() const { return _rowset_meta_pb.empty(); }
212
213
358k
    void set_empty(bool empty) { _rowset_meta_pb.set_empty(empty); }
214
215
98
    PUniqueId load_id() const { return _rowset_meta_pb.load_id(); }
216
217
314k
    void set_load_id(PUniqueId load_id) {
218
314k
        PUniqueId* new_load_id = _rowset_meta_pb.mutable_load_id();
219
314k
        new_load_id->set_hi(load_id.hi());
220
314k
        new_load_id->set_lo(load_id.lo());
221
314k
    }
222
223
205k
    void set_job_id(const std::string& job_id) { _rowset_meta_pb.set_job_id(job_id); }
224
225
0
    const std::string& job_id() const { return _rowset_meta_pb.job_id(); }
226
227
0
    bool delete_flag() const { return _rowset_meta_pb.delete_flag(); }
228
229
126k
    int64_t creation_time() const { return _rowset_meta_pb.creation_time(); }
230
231
358k
    void set_creation_time(int64_t creation_time) {
232
358k
        return _rowset_meta_pb.set_creation_time(creation_time);
233
358k
    }
234
235
533k
    int64_t stale_at() const {
236
533k
        int64_t stale_time = _stale_at_s.load();
237
533k
        return stale_time > 0 ? stale_time : _rowset_meta_pb.creation_time();
238
533k
    }
239
240
4.32k
    bool has_stale_at() const { return _stale_at_s.load() > 0; }
241
242
79.9k
    void set_stale_at(int64_t stale_at) { _stale_at_s.store(stale_at); }
243
244
2.47k
    int64_t partition_id() const { return _rowset_meta_pb.partition_id(); }
245
246
336k
    void set_partition_id(int64_t partition_id) {
247
336k
        return _rowset_meta_pb.set_partition_id(partition_id);
248
336k
    }
249
250
30.2M
    int64_t num_segments() const { return _rowset_meta_pb.num_segments(); }
251
252
363k
    void set_num_segments(int64_t num_segments) { _rowset_meta_pb.set_num_segments(num_segments); }
253
254
    // Convert to RowsetMetaPB, skip_schema is only used by cloud to separate schema from rowset meta.
255
    void to_rowset_pb(RowsetMetaPB* rs_meta_pb, bool skip_schema = false) const;
256
257
    // Convert to RowsetMetaPB, skip_schema is only used by cloud to separate schema from rowset meta.
258
    RowsetMetaPB get_rowset_pb(bool skip_schema = false) const;
259
260
0
    inline DeletePredicatePB* mutable_delete_pred_pb() {
261
0
        return _rowset_meta_pb.mutable_delete_predicate();
262
0
    }
263
264
1.54k
    bool is_singleton_delta() const {
265
1.54k
        return has_version() && _rowset_meta_pb.start_version() == _rowset_meta_pb.end_version();
266
1.54k
    }
267
268
    // Some time, we may check if this rowset is in rowset meta manager's meta by using RowsetMetaManager::check_rowset_meta.
269
    // But, this check behavior may cost a lot of time when it is frequent.
270
    // If we explicitly remove this rowset from rowset meta manager's meta, we can set _is_removed_from_rowset_meta to true,
271
    // And next time when we want to check if this rowset is in rowset mata manager's meta, we can
272
    // check is_remove_from_rowset_meta() first.
273
1.31k
    void set_remove_from_rowset_meta() { _is_removed_from_rowset_meta = true; }
274
275
1.31k
    bool is_remove_from_rowset_meta() const { return _is_removed_from_rowset_meta; }
276
277
34.5k
    SegmentsOverlapPB segments_overlap() const { return _rowset_meta_pb.segments_overlap_pb(); }
278
279
422k
    void set_segments_overlap(SegmentsOverlapPB segments_overlap) {
280
422k
        _rowset_meta_pb.set_segments_overlap_pb(segments_overlap);
281
422k
    }
282
283
462k
    static bool comparator(const RowsetMetaSharedPtr& left, const RowsetMetaSharedPtr& right) {
284
462k
        return left->end_version() < right->end_version();
285
462k
    }
286
287
    // return true if segments in this rowset has overlapping data.
288
    // this is not same as `segments_overlap()` method.
289
    // `segments_overlap()` only return the value of "segments_overlap" field in rowset meta,
290
    // but "segments_overlap" may be UNKNOWN.
291
    //
292
    // Returns true if all of the following conditions are met
293
    // 1. the rowset contains more than one segment
294
    // 2. the rowset's start version == end version (non-singleton rowset was generated by compaction process
295
    //    which always produces non-overlapped segments)
296
    // 3. segments_overlap() flag is not NONOVERLAPPING (OVERLAP_UNKNOWN and OVERLAPPING are OK)
297
5.35M
    bool is_segments_overlapping() const {
298
5.35M
        return num_segments() > 1 && is_singleton_delta() && segments_overlap() != NONOVERLAPPING;
299
5.35M
    }
300
301
30
    bool produced_by_compaction() const {
302
30
        return has_version() &&
303
31
               (start_version() < end_version() ||
304
31
                (start_version() == end_version() && segments_overlap() == NONOVERLAPPING));
305
30
    }
306
307
    // get the compaction score of this rowset.
308
    // if segments are overlapping, the score equals to the number of segments,
309
    // otherwise, score is 1.
310
1.74M
    uint32_t get_compaction_score() const {
311
1.74M
        uint32_t score = 0;
312
1.74M
        if (!is_segments_overlapping()) {
313
1.74M
            score = 1;
314
18.4E
        } else {
315
18.4E
            auto num_seg = num_segments();
316
18.4E
            DCHECK_GT(num_seg, 0);
317
18.4E
            score = cast_set<uint32_t>(num_seg);
318
18.4E
            CHECK(score > 0);
319
18.4E
        }
320
1.74M
        return score;
321
1.74M
    }
322
323
75.7k
    uint32_t get_merge_way_num() const {
324
75.7k
        uint32_t way_num = 0;
325
76.1k
        if (!is_segments_overlapping()) {
326
76.1k
            if (num_segments() == 0) {
327
49.8k
                way_num = 0;
328
49.8k
            } else {
329
26.2k
                way_num = 1;
330
26.2k
            }
331
18.4E
        } else {
332
18.4E
            auto num_seg = num_segments();
333
18.4E
            DCHECK_GT(num_seg, 0);
334
335
18.4E
            way_num = cast_set<uint32_t>(num_seg);
336
18.4E
            CHECK(way_num > 0);
337
18.4E
        }
338
75.7k
        return way_num;
339
75.7k
    }
340
341
4.16M
    void get_segments_key_bounds(std::vector<KeyBoundsPB>* segments_key_bounds) const {
342
4.16M
        for (const KeyBoundsPB& key_range : _rowset_meta_pb.segments_key_bounds()) {
343
3.98M
            segments_key_bounds->push_back(key_range);
344
3.98M
        }
345
4.16M
    }
346
347
1.43k
    auto& get_segments_key_bounds() const { return _rowset_meta_pb.segments_key_bounds(); }
348
349
5.09M
    bool is_segments_key_bounds_truncated() const {
350
5.09M
        return _rowset_meta_pb.has_segments_key_bounds_truncated() &&
351
5.09M
               _rowset_meta_pb.segments_key_bounds_truncated();
352
5.09M
    }
353
354
229k
    void set_segments_key_bounds_truncated(bool truncated) {
355
229k
        _rowset_meta_pb.set_segments_key_bounds_truncated(truncated);
356
229k
    }
357
358
1.00M
    bool get_first_segment_key_bound(KeyBoundsPB* key_bounds) {
359
        // for compatibility, old version has not segment key bounds
360
1.00M
        if (_rowset_meta_pb.segments_key_bounds_size() == 0) {
361
0
            return false;
362
0
        }
363
1.00M
        *key_bounds = *_rowset_meta_pb.segments_key_bounds().begin();
364
1.00M
        return true;
365
1.00M
    }
366
367
671k
    bool get_last_segment_key_bound(KeyBoundsPB* key_bounds) {
368
671k
        if (_rowset_meta_pb.segments_key_bounds_size() == 0) {
369
0
            return false;
370
0
        }
371
671k
        *key_bounds = *_rowset_meta_pb.segments_key_bounds().rbegin();
372
671k
        return true;
373
671k
    }
374
375
    void set_segments_key_bounds(const std::vector<KeyBoundsPB>& segments_key_bounds);
376
377
21
    void add_segment_key_bounds(KeyBoundsPB segments_key_bounds) {
378
21
        *_rowset_meta_pb.add_segments_key_bounds() = std::move(segments_key_bounds);
379
21
        set_segments_overlap(OVERLAPPING);
380
21
    }
381
382
337k
    void set_newest_write_timestamp(int64_t timestamp) {
383
337k
        _rowset_meta_pb.set_newest_write_timestamp(timestamp);
384
337k
    }
385
386
359k
    int64_t newest_write_timestamp() const { return _rowset_meta_pb.newest_write_timestamp(); }
387
388
    // for cloud only
389
313
    bool has_visible_ts_ms() const { return _rowset_meta_pb.has_visible_ts_ms(); }
390
306
    int64_t visible_ts_ms() const { return _rowset_meta_pb.visible_ts_ms(); }
391
313
    std::chrono::time_point<std::chrono::system_clock> visible_timestamp() const {
392
313
        using namespace std::chrono;
393
313
        if (has_visible_ts_ms()) {
394
306
            return time_point<system_clock>(milliseconds(visible_ts_ms()));
395
306
        }
396
7
        return system_clock::from_time_t(newest_write_timestamp());
397
313
    }
398
#ifdef BE_TEST
399
    void set_visible_ts_ms(int64_t visible_ts_ms) {
400
        _rowset_meta_pb.set_visible_ts_ms(visible_ts_ms);
401
    }
402
#endif
403
404
    void set_tablet_schema(const TabletSchemaSPtr& tablet_schema);
405
    void set_tablet_schema(const TabletSchemaPB& tablet_schema);
406
407
7.01M
    const TabletSchemaSPtr& tablet_schema() const { return _schema; }
408
409
203k
    void set_txn_expiration(int64_t expiration) { _rowset_meta_pb.set_txn_expiration(expiration); }
410
411
204k
    void set_compaction_level(int64_t compaction_level) {
412
204k
        _rowset_meta_pb.set_compaction_level(compaction_level);
413
204k
    }
414
415
4.45k
    int64_t compaction_level() { return _rowset_meta_pb.compaction_level(); }
416
417
    // `seg_file_size` MUST ordered by segment id
418
    void add_segments_file_size(const std::vector<size_t>& seg_file_size);
419
420
    // Return -1 if segment file size is unknown
421
    int64_t segment_file_size(int seg_id) const;
422
423
1.37k
    const auto& segments_file_size() const { return _rowset_meta_pb.segments_file_size(); }
424
425
    // Used for partial update, when publish, partial update may add a new rowset and we should update rowset meta
426
    void merge_rowset_meta(const RowsetMeta& other);
427
428
    InvertedIndexFileInfo inverted_index_file_info(int seg_id);
429
430
176
    const auto& inverted_index_file_info() const {
431
176
        return _rowset_meta_pb.inverted_index_file_info();
432
176
    }
433
434
    void add_inverted_index_files_info(
435
            const std::vector<const InvertedIndexFileInfo*>& idx_file_info);
436
437
    int64_t get_metadata_size() const override;
438
439
    // Because the member field '_handle' is a raw pointer, use member func 'init' to replace copy ctor
440
    RowsetMeta(const RowsetMeta&) = delete;
441
    RowsetMeta operator=(const RowsetMeta&) = delete;
442
443
    void add_packed_slice_location(const std::string& segment_path,
444
                                   const std::string& packed_file_path, int64_t offset,
445
0
                                   int64_t size, int64_t packed_file_size) {
446
0
        auto* index_map = _rowset_meta_pb.mutable_packed_slice_locations();
447
0
        auto& index_pb = (*index_map)[segment_path];
448
0
        index_pb.set_packed_file_path(packed_file_path);
449
0
        index_pb.set_offset(offset);
450
0
        index_pb.set_size(size);
451
0
        index_pb.set_packed_file_size(packed_file_size);
452
0
    }
453
454
324
    int32_t schema_version() const { return _rowset_meta_pb.schema_version(); }
455
456
0
    std::string debug_string() const { return _rowset_meta_pb.ShortDebugString(); }
457
458
    // Pre-set the encryption algorithm to avoid re-entrant get_tablet calls
459
    // that can cause SingleFlight deadlock during tablet loading.
460
0
    void set_encryption_algorithm(EncryptionAlgorithmPB algorithm) {
461
0
        _determine_encryption_once.call(
462
0
                [algorithm]() -> Result<EncryptionAlgorithmPB> { return algorithm; });
463
0
    }
464
465
private:
466
    bool _deserialize_from_pb(std::string_view value);
467
468
    bool _serialize_to_pb(std::string* value);
469
470
    void _init();
471
472
    friend bool operator==(const RowsetMeta& a, const RowsetMeta& b);
473
474
0
    friend bool operator!=(const RowsetMeta& a, const RowsetMeta& b) { return !(a == b); }
475
476
private:
477
    RowsetMetaPB _rowset_meta_pb;
478
    TabletSchemaSPtr _schema;
479
    Cache::Handle* _handle = nullptr;
480
    RowsetId _rowset_id;
481
    StorageResource _storage_resource;
482
    bool _is_removed_from_rowset_meta = false;
483
    DorisCallOnce<Result<EncryptionAlgorithmPB>> _determine_encryption_once;
484
    std::atomic<int64_t> _stale_at_s {0};
485
};
486
487
using RowsetMetaMapContainer = std::unordered_map<Version, RowsetMetaSharedPtr, HashOfVersion>;
488
489
#include "common/compile_check_end.h"
490
} // namespace doris
491
492
#endif // DORIS_BE_SRC_OLAP_ROWSET_ROWSET_META_H