Coverage Report

Created: 2025-07-23 16:39

/root/doris/be/src/olap/olap_common.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 <gen_cpp/Types_types.h>
21
#include <netinet/in.h>
22
23
#include <atomic>
24
#include <charconv>
25
#include <cstdint>
26
#include <functional>
27
#include <list>
28
#include <map>
29
#include <memory>
30
#include <ostream>
31
#include <sstream>
32
#include <string>
33
#include <typeinfo>
34
#include <unordered_map>
35
#include <unordered_set>
36
#include <utility>
37
38
#include "common/config.h"
39
#include "io/io_common.h"
40
#include "olap/inverted_index_stats.h"
41
#include "olap/olap_define.h"
42
#include "olap/rowset/rowset_fwd.h"
43
#include "util/hash_util.hpp"
44
#include "util/time.h"
45
#include "util/uid_util.h"
46
47
namespace doris {
48
49
static constexpr int64_t MAX_ROWSET_ID = 1L << 56;
50
static constexpr int64_t LOW_56_BITS = 0x00ffffffffffffff;
51
52
using SchemaHash = int32_t;
53
using int128_t = __int128;
54
using uint128_t = unsigned __int128;
55
56
using TabletUid = UniqueId;
57
58
enum CompactionType { BASE_COMPACTION = 1, CUMULATIVE_COMPACTION = 2, FULL_COMPACTION = 3 };
59
60
enum DataDirType {
61
    SPILL_DISK_DIR,
62
    OLAP_DATA_DIR,
63
    DATA_CACHE_DIR,
64
};
65
66
struct DataDirInfo {
67
    std::string path;
68
    size_t path_hash = 0;
69
    int64_t disk_capacity = 1; // actual disk capacity
70
    int64_t available = 0;     // available space, in bytes unit
71
    int64_t local_used_capacity = 0;
72
    int64_t remote_used_capacity = 0;
73
    int64_t trash_used_capacity = 0;
74
    bool is_used = false;                                      // whether available mark
75
    TStorageMedium::type storage_medium = TStorageMedium::HDD; // Storage medium type: SSD|HDD
76
    DataDirType data_dir_type = DataDirType::OLAP_DATA_DIR;
77
    std::string metric_name;
78
};
79
struct PredicateFilterInfo {
80
    int type = 0;
81
    uint64_t input_row = 0;
82
    uint64_t filtered_row = 0;
83
};
84
// Sort DataDirInfo by available space.
85
struct DataDirInfoLessAvailability {
86
7
    bool operator()(const DataDirInfo& left, const DataDirInfo& right) const {
87
7
        return left.available < right.available;
88
7
    }
89
};
90
91
struct TabletInfo {
92
    TabletInfo(TTabletId in_tablet_id, UniqueId in_uid)
93
            : tablet_id(in_tablet_id), tablet_uid(in_uid) {}
94
95
    bool operator<(const TabletInfo& right) const {
96
        if (tablet_id != right.tablet_id) {
97
            return tablet_id < right.tablet_id;
98
        } else {
99
            return tablet_uid < right.tablet_uid;
100
        }
101
    }
102
103
    std::string to_string() const {
104
        std::stringstream ss;
105
        ss << tablet_id << "." << tablet_uid.to_string();
106
        return ss.str();
107
    }
108
109
    TTabletId tablet_id;
110
    UniqueId tablet_uid;
111
};
112
113
struct TabletSize {
114
    TabletSize(TTabletId in_tablet_id, size_t in_tablet_size)
115
0
            : tablet_id(in_tablet_id), tablet_size(in_tablet_size) {}
116
117
    TTabletId tablet_id;
118
    size_t tablet_size;
119
};
120
121
// Define all data types supported by Field.
122
// If new filed_type is defined, not only new TypeInfo may need be defined,
123
// but also some functions like get_type_info in types.cpp need to be changed.
124
enum class FieldType {
125
    OLAP_FIELD_TYPE_TINYINT = 1, // MYSQL_TYPE_TINY
126
    OLAP_FIELD_TYPE_UNSIGNED_TINYINT = 2,
127
    OLAP_FIELD_TYPE_SMALLINT = 3, // MYSQL_TYPE_SHORT
128
    OLAP_FIELD_TYPE_UNSIGNED_SMALLINT = 4,
129
    OLAP_FIELD_TYPE_INT = 5, // MYSQL_TYPE_LONG
130
    OLAP_FIELD_TYPE_UNSIGNED_INT = 6,
131
    OLAP_FIELD_TYPE_BIGINT = 7, // MYSQL_TYPE_LONGLONG
132
    OLAP_FIELD_TYPE_UNSIGNED_BIGINT = 8,
133
    OLAP_FIELD_TYPE_LARGEINT = 9,
134
    OLAP_FIELD_TYPE_FLOAT = 10,  // MYSQL_TYPE_FLOAT
135
    OLAP_FIELD_TYPE_DOUBLE = 11, // MYSQL_TYPE_DOUBLE
136
    OLAP_FIELD_TYPE_DISCRETE_DOUBLE = 12,
137
    OLAP_FIELD_TYPE_CHAR = 13,     // MYSQL_TYPE_STRING
138
    OLAP_FIELD_TYPE_DATE = 14,     // MySQL_TYPE_NEWDATE
139
    OLAP_FIELD_TYPE_DATETIME = 15, // MySQL_TYPE_DATETIME
140
    OLAP_FIELD_TYPE_DECIMAL = 16,  // DECIMAL, using different store format against MySQL
141
    OLAP_FIELD_TYPE_VARCHAR = 17,
142
143
    OLAP_FIELD_TYPE_STRUCT = 18,  // Struct
144
    OLAP_FIELD_TYPE_ARRAY = 19,   // ARRAY
145
    OLAP_FIELD_TYPE_MAP = 20,     // Map
146
    OLAP_FIELD_TYPE_UNKNOWN = 21, // UNKNOW OLAP_FIELD_TYPE_STRING
147
    OLAP_FIELD_TYPE_NONE = 22,
148
    OLAP_FIELD_TYPE_HLL = 23,
149
    OLAP_FIELD_TYPE_BOOL = 24,
150
    OLAP_FIELD_TYPE_OBJECT = 25,
151
    OLAP_FIELD_TYPE_STRING = 26,
152
    OLAP_FIELD_TYPE_QUANTILE_STATE = 27,
153
    OLAP_FIELD_TYPE_DATEV2 = 28,
154
    OLAP_FIELD_TYPE_DATETIMEV2 = 29,
155
    OLAP_FIELD_TYPE_TIMEV2 = 30,
156
    OLAP_FIELD_TYPE_DECIMAL32 = 31,
157
    OLAP_FIELD_TYPE_DECIMAL64 = 32,
158
    OLAP_FIELD_TYPE_DECIMAL128I = 33,
159
    OLAP_FIELD_TYPE_JSONB = 34,
160
    OLAP_FIELD_TYPE_VARIANT = 35,
161
    OLAP_FIELD_TYPE_AGG_STATE = 36,
162
    OLAP_FIELD_TYPE_DECIMAL256 = 37,
163
    OLAP_FIELD_TYPE_IPV4 = 38,
164
    OLAP_FIELD_TYPE_IPV6 = 39,
165
};
166
167
// Define all aggregation methods supported by Field
168
// Note that in practice, not all types can use all the following aggregation methods
169
// For example, it is meaningless to use SUM for the string type (but it will not cause the program to crash)
170
// The implementation of the Field class does not perform such checks, and should be constrained when creating the table
171
enum class FieldAggregationMethod {
172
    OLAP_FIELD_AGGREGATION_NONE = 0,
173
    OLAP_FIELD_AGGREGATION_SUM = 1,
174
    OLAP_FIELD_AGGREGATION_MIN = 2,
175
    OLAP_FIELD_AGGREGATION_MAX = 3,
176
    OLAP_FIELD_AGGREGATION_REPLACE = 4,
177
    OLAP_FIELD_AGGREGATION_HLL_UNION = 5,
178
    OLAP_FIELD_AGGREGATION_UNKNOWN = 6,
179
    OLAP_FIELD_AGGREGATION_BITMAP_UNION = 7,
180
    // Replace if and only if added value is not null
181
    OLAP_FIELD_AGGREGATION_REPLACE_IF_NOT_NULL = 8,
182
    OLAP_FIELD_AGGREGATION_QUANTILE_UNION = 9,
183
    OLAP_FIELD_AGGREGATION_GENERIC = 10
184
};
185
186
enum class PushType {
187
    PUSH_NORMAL = 1,          // for broker/hadoop load, not used any more
188
    PUSH_FOR_DELETE = 2,      // for delete
189
    PUSH_FOR_LOAD_DELETE = 3, // not used any more
190
    PUSH_NORMAL_V2 = 4,       // for spark load
191
};
192
193
constexpr bool field_is_slice_type(const FieldType& field_type) {
194
    return field_type == FieldType::OLAP_FIELD_TYPE_VARCHAR ||
195
           field_type == FieldType::OLAP_FIELD_TYPE_CHAR ||
196
           field_type == FieldType::OLAP_FIELD_TYPE_STRING;
197
}
198
199
0
constexpr bool field_is_numeric_type(const FieldType& field_type) {
200
0
    return field_type == FieldType::OLAP_FIELD_TYPE_INT ||
201
0
           field_type == FieldType::OLAP_FIELD_TYPE_UNSIGNED_INT ||
202
0
           field_type == FieldType::OLAP_FIELD_TYPE_BIGINT ||
203
0
           field_type == FieldType::OLAP_FIELD_TYPE_SMALLINT ||
204
0
           field_type == FieldType::OLAP_FIELD_TYPE_UNSIGNED_TINYINT ||
205
0
           field_type == FieldType::OLAP_FIELD_TYPE_UNSIGNED_SMALLINT ||
206
0
           field_type == FieldType::OLAP_FIELD_TYPE_TINYINT ||
207
0
           field_type == FieldType::OLAP_FIELD_TYPE_DOUBLE ||
208
0
           field_type == FieldType::OLAP_FIELD_TYPE_FLOAT ||
209
0
           field_type == FieldType::OLAP_FIELD_TYPE_DATE ||
210
0
           field_type == FieldType::OLAP_FIELD_TYPE_DATEV2 ||
211
0
           field_type == FieldType::OLAP_FIELD_TYPE_DATETIME ||
212
0
           field_type == FieldType::OLAP_FIELD_TYPE_DATETIMEV2 ||
213
0
           field_type == FieldType::OLAP_FIELD_TYPE_LARGEINT ||
214
0
           field_type == FieldType::OLAP_FIELD_TYPE_DECIMAL ||
215
0
           field_type == FieldType::OLAP_FIELD_TYPE_DECIMAL32 ||
216
0
           field_type == FieldType::OLAP_FIELD_TYPE_DECIMAL64 ||
217
0
           field_type == FieldType::OLAP_FIELD_TYPE_DECIMAL128I ||
218
0
           field_type == FieldType::OLAP_FIELD_TYPE_DECIMAL256 ||
219
0
           field_type == FieldType::OLAP_FIELD_TYPE_BOOL ||
220
0
           field_type == FieldType::OLAP_FIELD_TYPE_IPV4 ||
221
0
           field_type == FieldType::OLAP_FIELD_TYPE_IPV6;
222
0
}
223
224
// <start_version_id, end_version_id>, such as <100, 110>
225
//using Version = std::pair<TupleVersion, TupleVersion>;
226
227
struct Version {
228
    int64_t first;
229
    int64_t second;
230
231
1.82M
    Version(int64_t first_, int64_t second_) : first(first_), second(second_) {}
232
8.41k
    Version() : first(0), second(0) {}
233
234
    static Version mock() {
235
        // Every time SchemaChange is used for external rowing, some temporary versions (such as 999, 1000, 1001) will be written, in order to avoid Cache conflicts, temporary
236
        // The version number takes a BIG NUMBER plus the version number of the current SchemaChange
237
        return Version(1 << 28, 1 << 29);
238
    }
239
240
    friend std::ostream& operator<<(std::ostream& os, const Version& version);
241
242
    bool operator!=(const Version& rhs) const { return first != rhs.first || second != rhs.second; }
243
244
357k
    bool operator==(const Version& rhs) const { return first == rhs.first && second == rhs.second; }
  Branch (244:56): [True: 139, False: 357k]
  Branch (244:78): [True: 139, False: 0]
245
246
    bool contains(const Version& other) const {
247
        return first <= other.first && second >= other.second;
248
    }
249
250
987
    std::string to_string() const { return fmt::format("[{}-{}]", first, second); }
251
};
252
253
using Versions = std::vector<Version>;
254
255
13
inline std::ostream& operator<<(std::ostream& os, const Version& version) {
256
13
    return os << version.to_string();
257
13
}
258
259
inline std::ostream& operator<<(std::ostream& os, const Versions& versions) {
260
    for (auto& version : versions) {
261
        os << version;
262
    }
263
    return os;
264
}
265
266
// used for hash-struct of hash_map<Version, Rowset*>.
267
struct HashOfVersion {
268
11.8k
    size_t operator()(const Version& version) const {
269
11.8k
        size_t seed = 0;
270
11.8k
        seed = HashUtil::hash64(&version.first, sizeof(version.first), seed);
271
11.8k
        seed = HashUtil::hash64(&version.second, sizeof(version.second), seed);
272
11.8k
        return seed;
273
11.8k
    }
274
};
275
276
// It is used to represent Graph vertex.
277
struct Vertex {
278
    int64_t value = 0;
279
    std::list<int64_t> edges;
280
281
    Vertex(int64_t v) : value(v) {}
282
};
283
284
class Field;
285
class WrapperField;
286
using KeyRange = std::pair<WrapperField*, WrapperField*>;
287
288
// ReaderStatistics used to collect statistics when scan data from storage
289
struct OlapReaderStatistics {
290
    int64_t io_ns = 0;
291
    int64_t compressed_bytes_read = 0;
292
293
    int64_t decompress_ns = 0;
294
    int64_t uncompressed_bytes_read = 0;
295
296
    // total read bytes in memory
297
    int64_t bytes_read = 0;
298
299
    int64_t block_fetch_ns = 0; // time of rowset reader's `next_batch()` call
300
    int64_t block_load_ns = 0;
301
    int64_t blocks_load = 0;
302
    // Not used any more, will be removed after non-vectorized code is removed
303
    int64_t block_seek_num = 0;
304
    // Not used any more, will be removed after non-vectorized code is removed
305
    int64_t block_seek_ns = 0;
306
307
    // block_load_ns
308
    //      block_init_ns
309
    //          block_init_seek_ns
310
    //          generate_row_ranges_ns
311
    //      predicate_column_read_ns
312
    //          predicate_column_read_seek_ns
313
    //      lazy_read_ns
314
    //          block_lazy_read_seek_ns
315
    int64_t block_init_ns = 0;
316
    int64_t block_init_seek_num = 0;
317
    int64_t block_init_seek_ns = 0;
318
    int64_t predicate_column_read_ns = 0;
319
    int64_t non_predicate_read_ns = 0;
320
    int64_t predicate_column_read_seek_num = 0;
321
    int64_t predicate_column_read_seek_ns = 0;
322
    int64_t lazy_read_ns = 0;
323
    int64_t block_lazy_read_seek_num = 0;
324
    int64_t block_lazy_read_seek_ns = 0;
325
326
    int64_t raw_rows_read = 0;
327
328
    int64_t rows_vec_cond_filtered = 0;
329
    int64_t rows_short_circuit_cond_filtered = 0;
330
    int64_t vec_cond_input_rows = 0;
331
    int64_t short_circuit_cond_input_rows = 0;
332
    int64_t rows_vec_del_cond_filtered = 0;
333
    int64_t vec_cond_ns = 0;
334
    int64_t short_cond_ns = 0;
335
    int64_t expr_filter_ns = 0;
336
    int64_t output_col_ns = 0;
337
338
    std::map<int, PredicateFilterInfo> filter_info;
339
340
    int64_t rows_key_range_filtered = 0;
341
    int64_t rows_stats_filtered = 0;
342
    int64_t rows_stats_rp_filtered = 0;
343
    int64_t rows_bf_filtered = 0;
344
    int64_t rows_dict_filtered = 0;
345
    // Including the number of rows filtered out according to the Delete information in the Tablet,
346
    // and the number of rows filtered for marked deleted rows under the unique key model.
347
    // This metric is mainly used to record the number of rows filtered by the delete condition in Segment V1,
348
    // and it is also used to record the replaced rows in the Unique key model in the "Reader" class.
349
    // In segmentv2, if you want to get all filtered rows, you need the sum of "rows_del_filtered" and "rows_conditions_filtered".
350
    int64_t rows_del_filtered = 0;
351
    int64_t rows_del_by_bitmap = 0;
352
    // the number of rows filtered by various column indexes.
353
    int64_t rows_conditions_filtered = 0;
354
    int64_t generate_row_ranges_by_keys_ns = 0;
355
    int64_t generate_row_ranges_by_column_conditions_ns = 0;
356
    int64_t generate_row_ranges_by_bf_ns = 0;
357
    int64_t generate_row_ranges_by_zonemap_ns = 0;
358
    int64_t generate_row_ranges_by_dict_ns = 0;
359
360
    int64_t index_load_ns = 0;
361
362
    int64_t total_pages_num = 0;
363
    int64_t cached_pages_num = 0;
364
365
    int64_t rows_bitmap_index_filtered = 0;
366
    int64_t bitmap_index_filter_timer = 0;
367
368
    int64_t rows_inverted_index_filtered = 0;
369
    int64_t inverted_index_filter_timer = 0;
370
    int64_t inverted_index_query_timer = 0;
371
    int64_t inverted_index_query_cache_hit = 0;
372
    int64_t inverted_index_query_cache_miss = 0;
373
    int64_t inverted_index_query_null_bitmap_timer = 0;
374
    int64_t inverted_index_query_bitmap_copy_timer = 0;
375
    int64_t inverted_index_searcher_open_timer = 0;
376
    int64_t inverted_index_searcher_search_timer = 0;
377
    int64_t inverted_index_searcher_search_init_timer = 0;
378
    int64_t inverted_index_searcher_search_exec_timer = 0;
379
    int64_t inverted_index_searcher_cache_hit = 0;
380
    int64_t inverted_index_searcher_cache_miss = 0;
381
    int64_t inverted_index_downgrade_count = 0;
382
    InvertedIndexStatistics inverted_index_stats;
383
384
    int64_t output_index_result_column_timer = 0;
385
    // number of segment filtered by column stat when creating seg iterator
386
    int64_t filtered_segment_number = 0;
387
    // total number of segment
388
    int64_t total_segment_number = 0;
389
390
    io::FileCacheStatistics file_cache_stats;
391
    int64_t load_segments_timer = 0;
392
393
    int64_t collect_iterator_merge_next_timer = 0;
394
    int64_t collect_iterator_normal_next_timer = 0;
395
    int64_t delete_bitmap_get_agg_ns = 0;
396
397
    int64_t tablet_reader_init_timer_ns = 0;
398
    int64_t tablet_reader_capture_rs_readers_timer_ns = 0;
399
    int64_t tablet_reader_init_return_columns_timer_ns = 0;
400
    int64_t tablet_reader_init_keys_param_timer_ns = 0;
401
    int64_t tablet_reader_init_orderby_keys_param_timer_ns = 0;
402
    int64_t tablet_reader_init_conditions_param_timer_ns = 0;
403
    int64_t tablet_reader_init_delete_condition_param_timer_ns = 0;
404
    int64_t block_reader_vcollect_iter_init_timer_ns = 0;
405
    int64_t block_reader_rs_readers_init_timer_ns = 0;
406
    int64_t block_reader_build_heap_init_timer_ns = 0;
407
408
    int64_t rowset_reader_get_segment_iterators_timer_ns = 0;
409
    int64_t rowset_reader_create_iterators_timer_ns = 0;
410
    int64_t rowset_reader_init_iterators_timer_ns = 0;
411
    int64_t rowset_reader_load_segments_timer_ns = 0;
412
413
    int64_t segment_iterator_init_timer_ns = 0;
414
    int64_t segment_iterator_init_return_column_iterators_timer_ns = 0;
415
    int64_t segment_iterator_init_bitmap_index_iterators_timer_ns = 0;
416
    int64_t segment_iterator_init_inverted_index_iterators_timer_ns = 0;
417
418
    int64_t segment_create_column_readers_timer_ns = 0;
419
    int64_t segment_load_index_timer_ns = 0;
420
};
421
422
using ColumnId = uint32_t;
423
// Column unique id set
424
using UniqueIdSet = std::set<uint32_t>;
425
// Column unique Id -> column id map
426
using UniqueIdToColumnIdMap = std::map<ColumnId, ColumnId>;
427
428
// 8 bit rowset id version
429
// 56 bit, inc number from 1
430
// 128 bit backend uid, it is a uuid bit, id version
431
struct RowsetId {
432
    int8_t version = 0;
433
    int64_t hi = 0;
434
    int64_t mi = 0;
435
    int64_t lo = 0;
436
437
11.4k
    void init(std::string_view rowset_id_str) {
438
        // for new rowsetid its a 48 hex string
439
        // if the len < 48, then it is an old format rowset id
440
11.4k
        if (rowset_id_str.length() < 48) [[unlikely]] {
  Branch (440:13): [True: 69, False: 11.3k]
441
69
            int64_t high;
442
69
            auto [_, ec] = std::from_chars(rowset_id_str.data(),
443
69
                                           rowset_id_str.data() + rowset_id_str.length(), high);
444
69
            if (ec != std::errc {}) [[unlikely]] {
  Branch (444:17): [True: 1, False: 68]
445
1
                if (config::force_regenerate_rowsetid_on_start_error) {
  Branch (445:21): [True: 1, False: 0]
446
1
                    LOG(WARNING) << "failed to init rowset id: " << rowset_id_str;
447
1
                    high = MAX_ROWSET_ID - 1;
448
1
                } else {
449
0
                    LOG(FATAL) << "failed to init rowset id: " << rowset_id_str;
450
0
                }
451
1
            }
452
69
            init(1, high, 0, 0);
453
11.3k
        } else {
454
11.3k
            int64_t high = 0;
455
11.3k
            int64_t middle = 0;
456
11.3k
            int64_t low = 0;
457
11.3k
            from_hex(&high, rowset_id_str.substr(0, 16));
458
11.3k
            from_hex(&middle, rowset_id_str.substr(16, 16));
459
11.3k
            from_hex(&low, rowset_id_str.substr(32, 16));
460
11.3k
            init(high >> 56, high & LOW_56_BITS, middle, low);
461
11.3k
        }
462
11.4k
    }
463
464
    // to compatible with old version
465
1.14k
    void init(int64_t rowset_id) { init(1, rowset_id, 0, 0); }
466
467
28.7k
    void init(int64_t id_version, int64_t high, int64_t middle, int64_t low) {
468
28.7k
        version = id_version;
469
28.7k
        if (UNLIKELY(high >= MAX_ROWSET_ID)) {
Line
Count
Source
36
28.7k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 28.7k]
470
0
            LOG(FATAL) << "inc rowsetid is too large:" << high;
471
0
        }
472
28.7k
        hi = (id_version << 56) + (high & LOW_56_BITS);
473
28.7k
        mi = middle;
474
28.7k
        lo = low;
475
28.7k
    }
476
477
46.5k
    std::string to_string() const {
478
46.5k
        if (version < 2) {
  Branch (478:13): [True: 25.8k, False: 20.7k]
479
25.8k
            return std::to_string(hi & LOW_56_BITS);
480
25.8k
        } else {
481
20.7k
            char buf[48];
482
20.7k
            to_hex(hi, buf);
483
20.7k
            to_hex(mi, buf + 16);
484
20.7k
            to_hex(lo, buf + 32);
485
20.7k
            return {buf, 48};
486
20.7k
        }
487
46.5k
    }
488
489
    // std::unordered_map need this api
490
357k
    bool operator==(const RowsetId& rhs) const {
491
357k
        return hi == rhs.hi && mi == rhs.mi && lo == rhs.lo;
  Branch (491:16): [True: 775, False: 356k]
  Branch (491:32): [True: 775, False: 0]
  Branch (491:48): [True: 775, False: 0]
492
357k
    }
493
494
    bool operator!=(const RowsetId& rhs) const {
495
        return hi != rhs.hi || mi != rhs.mi || lo != rhs.lo;
496
    }
497
498
45.0M
    bool operator<(const RowsetId& rhs) const {
499
45.0M
        if (hi != rhs.hi) {
  Branch (499:13): [True: 4.61M, False: 40.4M]
500
4.61M
            return hi < rhs.hi;
501
40.4M
        } else if (mi != rhs.mi) {
  Branch (501:20): [True: 0, False: 40.4M]
502
0
            return mi < rhs.mi;
503
40.4M
        } else {
504
40.4M
            return lo < rhs.lo;
505
40.4M
        }
506
45.0M
    }
507
508
1.25k
    friend std::ostream& operator<<(std::ostream& out, const RowsetId& rowset_id) {
509
1.25k
        out << rowset_id.to_string();
510
1.25k
        return out;
511
1.25k
    }
512
};
513
514
using RowsetIdUnorderedSet = std::unordered_set<RowsetId>;
515
516
// Extract rowset id from filename, return uninitialized rowset id if filename is invalid
517
483
inline RowsetId extract_rowset_id(std::string_view filename) {
518
483
    RowsetId rowset_id;
519
483
    if (filename.ends_with(".dat")) {
  Branch (519:9): [True: 243, False: 240]
520
        // filename format: {rowset_id}_{segment_num}.dat
521
243
        auto end = filename.find('_');
522
243
        if (end == std::string::npos) {
  Branch (522:13): [True: 0, False: 243]
523
0
            return rowset_id;
524
0
        }
525
243
        rowset_id.init(filename.substr(0, end));
526
243
        return rowset_id;
527
243
    }
528
240
    if (filename.ends_with(".idx")) {
  Branch (528:9): [True: 240, False: 0]
529
        // filename format: {rowset_id}_{segment_num}_{index_id}.idx
530
240
        auto end = filename.find('_');
531
240
        if (end == std::string::npos) {
  Branch (531:13): [True: 0, False: 240]
532
0
            return rowset_id;
533
0
        }
534
240
        rowset_id.init(filename.substr(0, end));
535
240
        return rowset_id;
536
240
    }
537
0
    return rowset_id;
538
240
}
539
540
class DeleteBitmap;
541
// merge on write context
542
struct MowContext {
543
    MowContext(int64_t version, int64_t txnid, const RowsetIdUnorderedSet& ids,
544
               std::vector<RowsetSharedPtr> rowset_ptrs, std::shared_ptr<DeleteBitmap> db)
545
            : max_version(version),
546
              txn_id(txnid),
547
              rowset_ids(ids),
548
              rowset_ptrs(std::move(rowset_ptrs)),
549
8
              delete_bitmap(std::move(db)) {}
550
    int64_t max_version;
551
    int64_t txn_id;
552
    const RowsetIdUnorderedSet& rowset_ids;
553
    std::vector<RowsetSharedPtr> rowset_ptrs;
554
    std::shared_ptr<DeleteBitmap> delete_bitmap;
555
};
556
557
// used for controll compaction
558
struct VersionWithTime {
559
    std::atomic<int64_t> version;
560
    int64_t update_ts;
561
562
    VersionWithTime() : version(0), update_ts(MonotonicMillis()) {}
563
564
    void update_version_monoto(int64_t new_version) {
565
        int64_t cur_version = version.load(std::memory_order_relaxed);
566
        while (cur_version < new_version) {
567
            if (version.compare_exchange_strong(cur_version, new_version, std::memory_order_relaxed,
568
                                                std::memory_order_relaxed)) {
569
                update_ts = MonotonicMillis();
570
                break;
571
            }
572
        }
573
    }
574
};
575
576
} // namespace doris
577
578
// This intended to be a "good" hash function.  It may change from time to time.
579
template <>
580
struct std::hash<doris::RowsetId> {
581
1.80k
    size_t operator()(const doris::RowsetId& rowset_id) const {
582
1.80k
        size_t seed = 0;
583
1.80k
        seed = doris::HashUtil::xxHash64WithSeed((const char*)&rowset_id.hi, sizeof(rowset_id.hi),
584
1.80k
                                                 seed);
585
1.80k
        seed = doris::HashUtil::xxHash64WithSeed((const char*)&rowset_id.mi, sizeof(rowset_id.mi),
586
1.80k
                                                 seed);
587
1.80k
        seed = doris::HashUtil::xxHash64WithSeed((const char*)&rowset_id.lo, sizeof(rowset_id.lo),
588
1.80k
                                                 seed);
589
1.80k
        return seed;
590
1.80k
    }
591
};