Coverage Report

Created: 2026-07-07 13:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/information_schema/schema_tablets_scanner.cpp
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
#include "information_schema/schema_tablets_scanner.h"
19
20
#include <gen_cpp/Descriptors_types.h>
21
#include <gen_cpp/olap_common.pb.h>
22
23
#include <algorithm>
24
#include <cstddef>
25
#include <cstdint>
26
#include <memory>
27
#include <numeric>
28
#include <shared_mutex>
29
#include <string>
30
#include <utility>
31
#include <vector>
32
33
#include "cloud/cloud_storage_engine.h"
34
#include "cloud/cloud_tablet.h"
35
#include "cloud/cloud_tablet_mgr.h"
36
#include "cloud/config.h"
37
#include "common/status.h"
38
#include "core/data_type/define_primitive_type.h"
39
#include "core/string_ref.h"
40
#include "information_schema/schema_scanner.h"
41
#include "information_schema/schema_scanner_helper.h"
42
#include "runtime/exec_env.h"
43
#include "runtime/runtime_state.h"
44
#include "storage/storage_engine.h"
45
#include "storage/tablet/tablet_fwd.h"
46
#include "storage/tablet/tablet_manager.h"
47
48
namespace doris {
49
class Block;
50
51
namespace {
52
struct TabletInfoSnapshot {
53
    int64_t tablet_id = 0;
54
    int64_t replica_id = 0;
55
    int64_t partition_id = 0;
56
    std::string tablet_path;
57
    int64_t tablet_local_size = 0;
58
    int64_t tablet_remote_size = 0;
59
    int64_t version_count = 0;
60
    int64_t segment_count = 0;
61
    int64_t num_columns = 0;
62
    int64_t row_size = 0;
63
    int32_t compaction_score = 0;
64
    std::string compress_kind;
65
    bool is_used = false;
66
    bool is_alter_failed = false;
67
    int64_t create_time = 0;
68
    int64_t update_time = 0;
69
    bool is_overlap = false;
70
    std::vector<RowsetMetaSharedPtr> rowset_metas;
71
    std::vector<RowsetMetaSharedPtr> row_binlog_rowset_metas;
72
    RowsetSharedPtr max_version_rowset;
73
};
74
} // namespace
75
76
std::vector<SchemaScanner::ColumnDesc> SchemaTabletsScanner::_s_tbls_columns = {
77
        //   name,       type,          size,     is_null
78
        {"BE_ID", TYPE_BIGINT, sizeof(int64_t), true},
79
        {"TABLET_ID", TYPE_BIGINT, sizeof(int64_t), true},
80
        {"REPLICA_ID", TYPE_BIGINT, sizeof(int64_t), true},
81
        {"PARTITION_ID", TYPE_BIGINT, sizeof(int64_t), true},
82
        {"TABLET_PATH", TYPE_STRING, sizeof(StringRef), true},
83
        {"TABLET_LOCAL_SIZE", TYPE_BIGINT, sizeof(int64_t), true},
84
        {"TABLET_REMOTE_SIZE", TYPE_BIGINT, sizeof(int64_t), true},
85
        {"VERSION_COUNT", TYPE_BIGINT, sizeof(int64_t), true},
86
        {"SEGMENT_COUNT", TYPE_BIGINT, sizeof(int64_t), true},
87
        {"NUM_COLUMNS", TYPE_BIGINT, sizeof(int64_t), true},
88
        {"ROW_SIZE", TYPE_BIGINT, sizeof(int64_t), true},
89
        {"COMPACTION_SCORE", TYPE_INT, sizeof(int32_t), true},
90
        {"COMPRESS_KIND", TYPE_STRING, sizeof(StringRef), true},
91
        {"IS_USED", TYPE_BOOLEAN, sizeof(bool), true},
92
        {"IS_ALTER_FAILED", TYPE_BOOLEAN, sizeof(bool), true},
93
        {"CREATE_TIME", TYPE_DATETIME, sizeof(int64_t), true},
94
        {"UPDATE_TIME", TYPE_DATETIME, sizeof(int64_t), true},
95
        {"IS_OVERLAP", TYPE_BOOLEAN, sizeof(bool), true},
96
};
97
98
SchemaTabletsScanner::SchemaTabletsScanner()
99
0
        : SchemaScanner(_s_tbls_columns, TSchemaTableType::SCH_BACKEND_TABLETS) {};
100
101
0
Status SchemaTabletsScanner::start(RuntimeState* state) {
102
0
    if (!_is_init) {
103
0
        return Status::InternalError("used before initialized.");
104
0
    }
105
0
    _backend_id = state->backend_id();
106
0
    RETURN_IF_ERROR(_get_all_tablets());
107
0
    return Status::OK();
108
0
}
109
110
0
Status SchemaTabletsScanner::_get_all_tablets() {
111
0
    if (config::is_cloud_mode()) {
112
0
        auto tablets =
113
0
                ExecEnv::GetInstance()->storage_engine().to_cloud().tablet_mgr().get_all_tablet();
114
0
        std::ranges::for_each(tablets, [&](auto& tablet) {
115
0
            _tablets.push_back(std::static_pointer_cast<BaseTablet>(tablet));
116
0
        });
117
0
    } else {
118
0
        auto tablets = ExecEnv::GetInstance()
119
0
                               ->storage_engine()
120
0
                               .to_local()
121
0
                               .tablet_manager()
122
0
                               ->get_all_tablet();
123
0
        std::ranges::for_each(tablets, [&](auto& tablet) {
124
0
            _tablets.push_back(std::static_pointer_cast<BaseTablet>(tablet));
125
0
        });
126
0
    }
127
0
    return Status::OK();
128
0
}
129
130
0
Status SchemaTabletsScanner::get_next_block_internal(Block* block, bool* eos) {
131
0
    if (!_is_init) {
132
0
        return Status::InternalError("Used before initialized.");
133
0
    }
134
0
    if (nullptr == block || nullptr == eos) {
135
0
        return Status::InternalError("input pointer is nullptr.");
136
0
    }
137
0
    *eos = true;
138
0
    return _fill_block_impl(block);
139
0
}
140
141
0
Status SchemaTabletsScanner::_fill_block_impl(Block* block) {
142
0
    SCOPED_TIMER(_fill_block_timer);
143
144
0
    size_t row_num = _tablets.size();
145
0
    if (row_num == 0) {
146
0
        return Status::OK();
147
0
    }
148
149
0
    size_t fill_tablets_num = _tablets.size();
150
0
    std::vector<void*> datas(fill_tablets_num);
151
152
0
    for (int i = 0; i < _tablets.size(); i++) {
153
0
        BaseTabletSPtr tablet = _tablets[i];
154
0
        TabletInfoSnapshot snapshot;
155
0
        {
156
            // Snapshot rowset maps under the tablet header lock because compaction rewrites them
157
            // under the same lock. Heavy aggregation and block filling run after releasing it.
158
0
            std::shared_lock rlock(tablet->get_header_lock());
159
0
            const auto& tablet_meta = tablet->tablet_meta();
160
0
            const auto& rs_metas = tablet_meta->all_rs_metas();
161
0
            const auto& row_binlog_rs_metas = tablet_meta->all_row_binlog_rs_metas();
162
163
0
            snapshot.tablet_id = tablet_meta->tablet_id();
164
0
            snapshot.replica_id = tablet_meta->replica_id();
165
0
            snapshot.partition_id = tablet_meta->partition_id();
166
0
            snapshot.tablet_path = tablet->tablet_path();
167
0
            snapshot.num_columns = static_cast<int64_t>(tablet_meta->tablet_columns_num());
168
0
            snapshot.row_size = static_cast<int64_t>(tablet->row_size());
169
0
            snapshot.compress_kind = CompressKind_Name(tablet->compress_kind());
170
0
            snapshot.is_used = [&tablet]() {
171
0
                if (config::is_cloud_mode()) {
172
0
                    return true;
173
0
                }
174
0
                return std::static_pointer_cast<Tablet>(tablet)->is_used();
175
0
            }();
176
0
            snapshot.is_alter_failed = tablet->is_alter_failed();
177
0
            snapshot.create_time = tablet_meta->creation_time();
178
0
            snapshot.rowset_metas.reserve(rs_metas.size());
179
0
            for (const auto& [_, rs_meta] : rs_metas) {
180
0
                snapshot.rowset_metas.emplace_back(rs_meta);
181
0
            }
182
0
            snapshot.row_binlog_rowset_metas.reserve(row_binlog_rs_metas.size());
183
0
            for (const auto& [_, rs_meta] : row_binlog_rs_metas) {
184
0
                snapshot.row_binlog_rowset_metas.emplace_back(rs_meta);
185
0
            }
186
0
            snapshot.max_version_rowset = tablet->get_rowset_with_max_version();
187
0
        }
188
189
0
        snapshot.tablet_local_size =
190
0
                std::accumulate(
191
0
                        snapshot.rowset_metas.begin(), snapshot.rowset_metas.end(), int64_t {0},
192
0
                        [](int64_t total_size, const auto& rs_meta) {
193
0
                            if (rs_meta->is_local()) {
194
0
                                total_size += static_cast<int64_t>(rs_meta->total_disk_size());
195
0
                            }
196
0
                            return total_size;
197
0
                        }) +
198
0
                std::accumulate(snapshot.row_binlog_rowset_metas.begin(),
199
0
                                snapshot.row_binlog_rowset_metas.end(), int64_t {0},
200
0
                                [](int64_t total_size, const auto& rs_meta) {
201
0
                                    if (rs_meta->is_local()) {
202
0
                                        total_size +=
203
0
                                                static_cast<int64_t>(rs_meta->data_disk_size());
204
0
                                    }
205
0
                                    return total_size;
206
0
                                });
207
0
        snapshot.tablet_remote_size = std::accumulate(
208
0
                snapshot.rowset_metas.begin(), snapshot.rowset_metas.end(), int64_t {0},
209
0
                [](int64_t total_size, const auto& rs_meta) {
210
0
                    if (!rs_meta->is_local()) {
211
0
                        total_size += static_cast<int64_t>(rs_meta->total_disk_size());
212
0
                    }
213
0
                    return total_size;
214
0
                });
215
0
        snapshot.version_count = static_cast<int64_t>(snapshot.rowset_metas.size());
216
0
        snapshot.segment_count =
217
0
                std::accumulate(snapshot.rowset_metas.begin(), snapshot.rowset_metas.end(),
218
0
                                int64_t {0}, [](int64_t val, const auto& rs_meta) {
219
0
                                    return val + static_cast<int64_t>(rs_meta->num_segments());
220
0
                                });
221
0
        snapshot.compaction_score = static_cast<int32_t>(std::accumulate(
222
0
                snapshot.rowset_metas.begin(), snapshot.rowset_metas.end(), uint32_t {0},
223
0
                [](uint32_t score, const auto& rs_meta) {
224
0
                    return score + static_cast<uint32_t>(rs_meta->get_compaction_score());
225
0
                }));
226
0
        snapshot.update_time = snapshot.max_version_rowset == nullptr
227
0
                                       ? 0
228
0
                                       : snapshot.max_version_rowset->newest_write_timestamp();
229
0
        snapshot.is_overlap =
230
0
                std::any_of(snapshot.rowset_metas.begin(), snapshot.rowset_metas.end(),
231
0
                            [](const auto& rs_meta) { return rs_meta->is_segments_overlapping(); });
232
233
        // BE_ID
234
0
        SchemaScannerHelper::insert_int64_value(0, _backend_id, block);
235
236
        // TABLET_ID
237
0
        SchemaScannerHelper::insert_int64_value(1, snapshot.tablet_id, block);
238
239
        // REPLICA_ID
240
0
        SchemaScannerHelper::insert_int64_value(2, snapshot.replica_id, block);
241
242
        // PARTITION_ID
243
0
        SchemaScannerHelper::insert_int64_value(3, snapshot.partition_id, block);
244
245
        // TABLET_PATH
246
0
        SchemaScannerHelper::insert_string_value(4, snapshot.tablet_path, block);
247
248
        // TABLET_LOCAL_SIZE
249
0
        SchemaScannerHelper::insert_int64_value(5, snapshot.tablet_local_size, block);
250
251
        // TABLET_REMOTE_SIZE
252
0
        SchemaScannerHelper::insert_int64_value(6, snapshot.tablet_remote_size, block);
253
254
        // VERSION_COUNT
255
0
        SchemaScannerHelper::insert_int64_value(7, snapshot.version_count, block);
256
257
        // SEGMENT_COUNT
258
0
        SchemaScannerHelper::insert_int64_value(8, snapshot.segment_count, block);
259
260
        // NUM_COLUMNS
261
0
        SchemaScannerHelper::insert_int64_value(9, snapshot.num_columns, block);
262
263
        // ROW_SIZE
264
0
        SchemaScannerHelper::insert_int64_value(10, snapshot.row_size, block);
265
266
        // COMPACTION_SCORE
267
0
        SchemaScannerHelper::insert_int32_value(11, snapshot.compaction_score, block);
268
269
        // COMPRESS_KIND
270
0
        SchemaScannerHelper::insert_string_value(12, snapshot.compress_kind, block);
271
272
        // IS_USED
273
0
        SchemaScannerHelper::insert_bool_value(13, snapshot.is_used, block);
274
275
        // IS_ALTER_FAILED
276
0
        SchemaScannerHelper::insert_bool_value(14, snapshot.is_alter_failed, block);
277
278
        // CREATE_TIME
279
0
        SchemaScannerHelper::insert_datetime_value(15, snapshot.create_time, _timezone_obj, block);
280
281
        // UPDATE_TIME
282
0
        SchemaScannerHelper::insert_datetime_value(16, snapshot.update_time, _timezone_obj, block);
283
284
        // IS_OVERLAP
285
0
        SchemaScannerHelper::insert_bool_value(17, snapshot.is_overlap, block);
286
0
    }
287
288
0
    return Status::OK();
289
0
}
290
} // namespace doris