Coverage Report

Created: 2026-07-21 11:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/format/jni/jni_reader.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 "jni_reader.h"
19
20
#include <glog/logging.h>
21
22
#include <map>
23
#include <ostream>
24
#include <sstream>
25
#include <tuple>
26
#include <unordered_map>
27
#include <utility>
28
29
#include "core/block/block.h"
30
#include "core/types.h"
31
#include "format/jni/jni_data_bridge.h"
32
#include "format/table/partition_column_filler.h"
33
#include "runtime/descriptors.h"
34
#include "runtime/runtime_state.h"
35
#include "util/jni-util.h"
36
37
namespace doris {
38
class RuntimeProfile;
39
class RuntimeState;
40
41
class Block;
42
} // namespace doris
43
44
namespace doris {
45
46
const std::vector<SlotDescriptor*> JniReader::_s_empty_slot_descs;
47
48
// =========================================================================
49
// JniReader constructors
50
// =========================================================================
51
52
JniReader::JniReader(const std::vector<SlotDescriptor*>& file_slot_descs, RuntimeState* state,
53
                     RuntimeProfile* profile, std::string connector_class,
54
                     std::map<std::string, std::string> scanner_params,
55
                     std::vector<std::string> column_names, int64_t self_split_weight)
56
6
        : _file_slot_descs(file_slot_descs),
57
6
          _state(state),
58
6
          _profile(profile),
59
6
          _connector_class(std::move(connector_class)),
60
6
          _scanner_params(std::move(scanner_params)),
61
6
          _column_names(std::move(column_names)),
62
6
          _self_split_weight(static_cast<int32_t>(self_split_weight)) {
63
6
    _connector_name = split(_connector_class, "/").back();
64
6
}
65
66
JniReader::JniReader(std::string connector_class, std::map<std::string, std::string> scanner_params)
67
3
        : _file_slot_descs(_s_empty_slot_descs),
68
3
          _connector_class(std::move(connector_class)),
69
3
          _scanner_params(std::move(scanner_params)) {
70
3
    _is_table_schema = true;
71
3
    _connector_name = split(_connector_class, "/").back();
72
3
}
73
74
3
Status JniReader::on_before_init_reader(ReaderInitContext* ctx) {
75
3
    _column_descs = ctx->column_descs;
76
3
    if (_col_name_to_block_idx == nullptr) {
77
3
        _col_name_to_block_idx = ctx->col_name_to_block_idx;
78
3
    }
79
3
    _partition_values.clear();
80
3
    _partition_value_is_null.clear();
81
3
    if (ctx->range == nullptr || ctx->tuple_descriptor == nullptr ||
82
3
        !ctx->range->__isset.columns_from_path_keys) {
83
3
        return Status::OK();
84
3
    }
85
86
0
    DORIS_CHECK(ctx->range->__isset.columns_from_path);
87
0
    DORIS_CHECK(ctx->range->columns_from_path.size() == ctx->range->columns_from_path_keys.size());
88
0
    const bool has_null_flags = ctx->range->__isset.columns_from_path_is_null;
89
0
    if (has_null_flags) {
90
0
        DORIS_CHECK(ctx->range->columns_from_path_is_null.size() ==
91
0
                    ctx->range->columns_from_path_keys.size());
92
0
    }
93
94
0
    std::unordered_map<std::string, const SlotDescriptor*> name_to_slot;
95
0
    for (auto* slot : ctx->tuple_descriptor->slots()) {
96
0
        name_to_slot.emplace(slot->col_name(), slot);
97
0
    }
98
0
    for (size_t i = 0; i < ctx->range->columns_from_path_keys.size(); ++i) {
99
0
        const auto& key = ctx->range->columns_from_path_keys[i];
100
0
        auto slot_it = name_to_slot.find(key);
101
0
        if (slot_it == name_to_slot.end()) {
102
0
            continue;
103
0
        }
104
0
        _partition_values.emplace(
105
0
                key, std::make_tuple(ctx->range->columns_from_path[i], slot_it->second));
106
0
        _partition_value_is_null.emplace(
107
0
                key, has_null_flags ? ctx->range->columns_from_path_is_null[i] : false);
108
0
    }
109
0
    return Status::OK();
110
3
}
111
112
4
Status JniReader::on_after_read_block(Block* block, size_t* read_rows) {
113
4
    if (_column_descs == nullptr || _partition_values.empty() || *read_rows == 0 ||
114
4
        _push_down_agg_type == TPushAggOp::type::COUNT) {
115
4
        return Status::OK();
116
4
    }
117
0
    return _fill_partition_columns(block, *read_rows);
118
4
}
119
120
// =========================================================================
121
// JniReader::open  (merged from JniConnector::open)
122
// =========================================================================
123
124
5
Status JniReader::open(RuntimeState* state, RuntimeProfile* profile) {
125
5
    _state = state;
126
5
    _profile = profile;
127
5
    if (_profile) {
128
2
        ADD_TIMER(_profile, _connector_name.c_str());
129
2
        _open_scanner_time = ADD_CHILD_TIMER(_profile, "OpenScannerTime", _connector_name.c_str());
130
2
        _java_scan_time = ADD_CHILD_TIMER(_profile, "JavaScanTime", _connector_name.c_str());
131
2
        _java_append_data_time =
132
2
                ADD_CHILD_TIMER(_profile, "JavaAppendDataTime", _connector_name.c_str());
133
2
        _java_create_vector_table_time =
134
2
                ADD_CHILD_TIMER(_profile, "JavaCreateVectorTableTime", _connector_name.c_str());
135
2
        _fill_block_time = ADD_CHILD_TIMER(_profile, "FillBlockTime", _connector_name.c_str());
136
2
        _max_time_split_weight_counter = _profile->add_conditition_counter(
137
2
                "MaxTimeSplitWeight", TUnit::UNIT, [](int64_t _c, int64_t c) { return c > _c; },
138
2
                _connector_name.c_str());
139
2
    }
140
5
    _java_scan_watcher = 0;
141
142
5
    JNIEnv* env = nullptr;
143
5
    int batch_size = 0;
144
5
    if (!_is_table_schema && _state) {
145
2
        batch_size = _state->batch_size();
146
2
    }
147
5
    _batch_size = batch_size;
148
5
    RETURN_IF_ERROR(Jni::Env::Get(&env));
149
5
    SCOPED_RAW_TIMER(&_jni_scanner_open_watcher);
150
5
    if (_state) {
151
2
        _scanner_params.emplace("time_zone", _state->timezone());
152
2
    }
153
5
    RETURN_IF_ERROR(_init_jni_scanner(env, batch_size));
154
    // Call org.apache.doris.common.jni.JniScanner#open
155
5
    RETURN_IF_ERROR(_jni_scanner_obj.call_void_method(env, _jni_scanner_open).call());
156
157
5
    RETURN_ERROR_IF_EXC(env);
158
5
    _scanner_opened = true;
159
5
    return Status::OK();
160
5
}
161
162
0
Status JniReader::publish_current_split_profile() {
163
0
    if (_profile == nullptr) {
164
0
        return Status::OK();
165
0
    }
166
0
    JNIEnv* env = nullptr;
167
0
    RETURN_IF_ERROR(Jni::Env::Get(&env));
168
0
    return _publish_current_split_profile(env);
169
0
}
170
171
5
Status JniReader::_publish_current_split_profile(JNIEnv* env) {
172
5
    DORIS_CHECK(env != nullptr);
173
5
    if (_profile == nullptr) {
174
3
        return Status::OK();
175
3
    }
176
177
2
    COUNTER_UPDATE(_open_scanner_time, _jni_scanner_open_watcher);
178
2
    COUNTER_UPDATE(_fill_block_time, _fill_block_watcher);
179
180
2
    RETURN_ERROR_IF_EXC(env);
181
2
    jlong append_data_time = 0;
182
2
    RETURN_IF_ERROR(_jni_scanner_obj.call_long_method(env, _jni_scanner_get_append_data_time)
183
2
                            .call(&append_data_time));
184
2
    jlong create_vector_table_time = 0;
185
2
    RETURN_IF_ERROR(
186
2
            _jni_scanner_obj.call_long_method(env, _jni_scanner_get_create_vector_table_time)
187
2
                    .call(&create_vector_table_time));
188
189
2
    const auto append_data_time_delta = append_data_time - _java_append_data_time_snapshot;
190
2
    const auto create_vector_table_time_delta =
191
2
            create_vector_table_time - _java_create_vector_table_time_snapshot;
192
2
    COUNTER_UPDATE(_java_append_data_time, append_data_time_delta);
193
2
    COUNTER_UPDATE(_java_create_vector_table_time, create_vector_table_time_delta);
194
2
    COUNTER_UPDATE(_java_scan_time,
195
2
                   _java_scan_watcher - append_data_time_delta - create_vector_table_time_delta);
196
2
    const auto split_time = _jni_scanner_open_watcher + _fill_block_watcher + _java_scan_watcher;
197
2
    if (split_time > 0) {
198
2
        _max_time_split_weight_counter->conditional_update(split_time, _self_split_weight);
199
2
    }
200
2
    _jni_scanner_open_watcher = 0;
201
2
    _java_scan_watcher = 0;
202
2
    _fill_block_watcher = 0;
203
2
    _java_append_data_time_snapshot = append_data_time;
204
2
    _java_create_vector_table_time_snapshot = create_vector_table_time;
205
2
    return Status::OK();
206
2
}
207
208
// =========================================================================
209
// JniReader::_do_get_next_block  (merged from JniConnector::get_next_block)
210
// =========================================================================
211
212
4
Status JniReader::_do_get_next_block(Block* block, size_t* read_rows, bool* eof) {
213
4
    JNIEnv* env = nullptr;
214
4
    RETURN_IF_ERROR(Jni::Env::Get(&env));
215
4
    long meta_address = 0;
216
4
    {
217
4
        SCOPED_RAW_TIMER(&_java_scan_watcher);
218
4
        RETURN_IF_ERROR(_jni_scanner_obj.call_long_method(env, _jni_scanner_get_next_batch)
219
4
                                .call(&meta_address));
220
4
    }
221
4
    if (meta_address == 0) {
222
2
        *read_rows = 0;
223
2
        *eof = true;
224
2
        return Status::OK();
225
2
    }
226
2
    _set_meta(meta_address);
227
2
    long num_rows = _table_meta.next_meta_as_long();
228
2
    if (num_rows == 0) {
229
0
        *read_rows = 0;
230
0
        *eof = true;
231
0
        return Status::OK();
232
0
    }
233
2
    RETURN_IF_ERROR(_fill_block(block, num_rows));
234
2
    *read_rows = num_rows;
235
2
    *eof = false;
236
2
    RETURN_IF_ERROR(_jni_scanner_obj.call_void_method(env, _jni_scanner_release_table).call());
237
2
    _has_read += num_rows;
238
2
    return Status::OK();
239
2
}
240
241
// =========================================================================
242
// JniReader::get_table_schema  (merged from JniConnector::get_table_schema)
243
// =========================================================================
244
245
0
Status JniReader::get_table_schema(std::string& table_schema_str) {
246
0
    JNIEnv* env = nullptr;
247
0
    RETURN_IF_ERROR(Jni::Env::Get(&env));
248
249
0
    Jni::LocalString jstr;
250
0
    RETURN_IF_ERROR(
251
0
            _jni_scanner_obj.call_object_method(env, _jni_scanner_get_table_schema).call(&jstr));
252
0
    Jni::LocalStringBufferGuard cstr;
253
0
    RETURN_IF_ERROR(jstr.get_string_chars(env, &cstr));
254
0
    table_schema_str = std::string {cstr.get()};
255
0
    return Status::OK();
256
0
}
257
258
// =========================================================================
259
// JniReader::close  (merged from JniConnector::close)
260
// =========================================================================
261
262
5
Status JniReader::close() {
263
5
    if (!_closed) {
264
5
        _closed = true;
265
5
        JNIEnv* env = nullptr;
266
5
        RETURN_IF_ERROR(Jni::Env::Get(&env));
267
5
        if (_scanner_opened) {
268
5
            RETURN_IF_ERROR(_publish_current_split_profile(env));
269
270
            // _fill_block may be failed and returned, we should release table in close.
271
            // org.apache.doris.common.jni.JniScanner#releaseTable is idempotent
272
5
            RETURN_IF_ERROR(
273
5
                    _jni_scanner_obj.call_void_method(env, _jni_scanner_release_table).call());
274
5
            RETURN_IF_ERROR(_jni_scanner_obj.call_void_method(env, _jni_scanner_close).call());
275
5
        }
276
5
    }
277
5
    return Status::OK();
278
5
}
279
280
// =========================================================================
281
// JniReader::set_batch_size
282
// =========================================================================
283
284
4
void JniReader::set_batch_size(size_t batch_size) {
285
4
    DCHECK_GT(batch_size, 0);
286
4
    if (_batch_size == batch_size) {
287
0
        return;
288
0
    }
289
4
    _batch_size = batch_size;
290
4
    if (_scanner_opened) {
291
4
        JNIEnv* env = nullptr;
292
4
        Status st = Jni::Env::Get(&env);
293
4
        if (!st) {
294
0
            LOG(WARNING) << "failed to get jni env when set_batch_size: " << st;
295
0
            return;
296
0
        }
297
4
        st = _jni_scanner_obj.call_void_method(env, _jni_scanner_set_batch_size)
298
4
                     .with_arg(static_cast<int>(_batch_size))
299
4
                     .call();
300
4
        if (!st) {
301
0
            LOG(WARNING) << "failed to call setBatchSize: " << st;
302
0
        }
303
4
    }
304
4
}
305
306
// =========================================================================
307
// JniReader::_init_jni_scanner  (merged from JniConnector::_init_jni_scanner)
308
// =========================================================================
309
310
5
Status JniReader::_init_jni_scanner(JNIEnv* env, int batch_size) {
311
5
    RETURN_IF_ERROR(
312
5
            Jni::Util::get_jni_scanner_class(env, _connector_class.c_str(), &_jni_scanner_cls));
313
314
5
    Jni::MethodId scanner_constructor;
315
5
    RETURN_IF_ERROR(_jni_scanner_cls.get_method(env, "<init>", "(ILjava/util/Map;)V",
316
5
                                                &scanner_constructor));
317
318
    // prepare constructor parameters
319
5
    Jni::LocalObject hashmap_object;
320
5
    RETURN_IF_ERROR(Jni::Util::convert_to_java_map(env, _scanner_params, &hashmap_object));
321
5
    RETURN_IF_ERROR(_jni_scanner_cls.new_object(env, scanner_constructor)
322
5
                            .with_arg(batch_size)
323
5
                            .with_arg(hashmap_object)
324
5
                            .call(&_jni_scanner_obj));
325
326
5
    RETURN_IF_ERROR(_jni_scanner_cls.get_method(env, "open", "()V", &_jni_scanner_open));
327
5
    RETURN_IF_ERROR(_jni_scanner_cls.get_method(env, "getNextBatchMeta", "()J",
328
5
                                                &_jni_scanner_get_next_batch));
329
5
    RETURN_IF_ERROR(_jni_scanner_cls.get_method(env, "getAppendDataTime", "()J",
330
5
                                                &_jni_scanner_get_append_data_time));
331
5
    RETURN_IF_ERROR(_jni_scanner_cls.get_method(env, "getCreateVectorTableTime", "()J",
332
5
                                                &_jni_scanner_get_create_vector_table_time));
333
5
    RETURN_IF_ERROR(_jni_scanner_cls.get_method(env, "getTableSchema", "()Ljava/lang/String;",
334
5
                                                &_jni_scanner_get_table_schema));
335
5
    RETURN_IF_ERROR(_jni_scanner_cls.get_method(env, "close", "()V", &_jni_scanner_close));
336
5
    RETURN_IF_ERROR(_jni_scanner_cls.get_method(env, "releaseColumn", "(I)V",
337
5
                                                &_jni_scanner_release_column));
338
5
    RETURN_IF_ERROR(
339
5
            _jni_scanner_cls.get_method(env, "releaseTable", "()V", &_jni_scanner_release_table));
340
5
    RETURN_IF_ERROR(_jni_scanner_cls.get_method(env, "getStatistics", "()Ljava/util/Map;",
341
5
                                                &_jni_scanner_get_statistics));
342
5
    RETURN_IF_ERROR(
343
5
            _jni_scanner_cls.get_method(env, "setBatchSize", "(I)V", &_jni_scanner_set_batch_size));
344
5
    RETURN_IF_ERROR(_jni_scanner_cls.get_method(env, "prepareForSplit", "(Ljava/util/Map;)V",
345
5
                                                &_jni_scanner_prepare_for_split));
346
5
    RETURN_IF_ERROR(_jni_scanner_cls.get_method(env, "resetCurrentSplit", "()V",
347
5
                                                &_jni_scanner_reset_current_split));
348
5
    return Status::OK();
349
5
}
350
351
// =========================================================================
352
// JniReader::_fill_block  (merged from JniConnector::_fill_block)
353
// =========================================================================
354
355
2
Status JniReader::_fill_block(Block* block, size_t num_rows) {
356
2
    SCOPED_RAW_TIMER(&_fill_block_watcher);
357
2
    JNIEnv* env = nullptr;
358
2
    RETURN_IF_ERROR(Jni::Env::Get(&env));
359
    // Fallback: if _col_name_to_block_idx was not set by the caller (e.g. JdbcScanner),
360
    // build the name-to-position map from the block itself.
361
2
    std::unordered_map<std::string, uint32_t> local_name_to_idx;
362
2
    const std::unordered_map<std::string, uint32_t>* col_map = _col_name_to_block_idx;
363
2
    if (col_map == nullptr) {
364
0
        local_name_to_idx = block->get_name_to_pos_map();
365
0
        col_map = &local_name_to_idx;
366
0
    }
367
4
    for (int i = 0; i < _column_names.size(); ++i) {
368
2
        auto& column_with_type_and_name = block->get_by_position(col_map->at(_column_names[i]));
369
2
        auto& column_ptr = column_with_type_and_name.column;
370
2
        auto& column_type = column_with_type_and_name.type;
371
2
        RETURN_IF_ERROR(JniDataBridge::fill_column(_table_meta, column_ptr, column_type, num_rows));
372
        // Column is not released when fill_column failed. It will be released when releasing table.
373
2
        RETURN_IF_ERROR(_jni_scanner_obj.call_void_method(env, _jni_scanner_release_column)
374
2
                                .with_arg(i)
375
2
                                .call());
376
2
        RETURN_ERROR_IF_EXC(env);
377
2
    }
378
2
    return Status::OK();
379
2
}
380
381
0
Status JniReader::_fill_partition_columns(Block* block, size_t num_rows) {
382
0
    std::unordered_map<std::string, uint32_t> local_name_to_idx;
383
0
    const std::unordered_map<std::string, uint32_t>* col_map = _col_name_to_block_idx;
384
0
    if (col_map == nullptr) {
385
0
        local_name_to_idx = block->get_name_to_pos_map();
386
0
        col_map = &local_name_to_idx;
387
0
    }
388
389
0
    for (const auto& desc : *_column_descs) {
390
0
        if (desc.category != ColumnCategory::PARTITION_KEY) {
391
0
            continue;
392
0
        }
393
0
        auto value_it = _partition_values.find(desc.name);
394
0
        if (value_it == _partition_values.end()) {
395
0
            continue;
396
0
        }
397
0
        auto col_it = col_map->find(desc.name);
398
0
        if (col_it == col_map->end()) {
399
0
            return Status::InternalError("Missing partition column {} in block {}", desc.name,
400
0
                                         block->dump_structure());
401
0
        }
402
403
0
        auto& column_with_type_and_name = block->get_by_position(col_it->second);
404
0
        auto mutable_column = std::move(*column_with_type_and_name.column).mutate();
405
0
        const auto& [value, slot_desc] = value_it->second;
406
0
        auto null_it = _partition_value_is_null.find(desc.name);
407
0
        DORIS_CHECK(null_it != _partition_value_is_null.end());
408
0
        RETURN_IF_ERROR(fill_partition_column_from_path_value(*mutable_column, *slot_desc, value,
409
0
                                                              num_rows, null_it->second));
410
0
        column_with_type_and_name.column = std::move(mutable_column);
411
0
    }
412
0
    return Status::OK();
413
0
}
414
415
// =========================================================================
416
// JniReader::_get_statistics  (merged from JniConnector::get_statistics)
417
// =========================================================================
418
419
2
Status JniReader::_get_statistics(JNIEnv* env, std::map<std::string, std::string>* result) {
420
2
    result->clear();
421
2
    Jni::LocalObject metrics;
422
2
    RETURN_IF_ERROR(
423
2
            _jni_scanner_obj.call_object_method(env, _jni_scanner_get_statistics).call(&metrics));
424
425
2
    RETURN_IF_ERROR(Jni::Util::convert_to_cpp_map(env, metrics, result));
426
2
    return Status::OK();
427
2
}
428
429
// =========================================================================
430
// JniReader::_collect_profile_before_close
431
// (merged from JniConnector::_collect_profile_before_close)
432
// =========================================================================
433
434
2
void JniReader::_collect_profile_before_close() {
435
2
    if (_scanner_opened && _profile != nullptr) {
436
2
        JNIEnv* env = nullptr;
437
2
        Status st = Jni::Env::Get(&env);
438
2
        if (!st) {
439
0
            LOG(WARNING) << "failed to get jni env when collect profile: " << st;
440
0
            return;
441
0
        }
442
        // update scanner metrics
443
2
        std::map<std::string, std::string> statistics_result;
444
2
        st = _get_statistics(env, &statistics_result);
445
2
        if (!st) {
446
0
            LOG(WARNING) << "failed to get_statistics when collect profile: " << st;
447
0
            return;
448
0
        }
449
450
2
        const auto update_peak = [](int64_t previous, int64_t current) {
451
0
            return current > previous;
452
0
        };
453
4
        for (const auto& metric : statistics_result) {
454
4
            std::vector<std::string> type_and_name = split(metric.first, ":");
455
4
            if (type_and_name.size() != 2) {
456
0
                LOG(WARNING) << "Name of JNI Scanner metric should be pattern like "
457
0
                             << "'metricType:metricName'";
458
0
                continue;
459
0
            }
460
4
            int64_t metric_value = std::stoll(metric.second);
461
4
            RuntimeProfile::Counter* scanner_counter;
462
4
            if (type_and_name[0] == "timer") {
463
2
                scanner_counter =
464
2
                        ADD_CHILD_TIMER(_profile, type_and_name[1], _connector_name.c_str());
465
2
                COUNTER_UPDATE(scanner_counter, metric_value);
466
2
            } else if (type_and_name[0] == "counter") {
467
2
                scanner_counter = ADD_CHILD_COUNTER(_profile, type_and_name[1], TUnit::UNIT,
468
2
                                                    _connector_name.c_str());
469
2
                COUNTER_UPDATE(scanner_counter, metric_value);
470
2
            } else if (type_and_name[0] == "bytes") {
471
0
                scanner_counter = ADD_CHILD_COUNTER(_profile, type_and_name[1], TUnit::BYTES,
472
0
                                                    _connector_name.c_str());
473
0
                COUNTER_UPDATE(scanner_counter, metric_value);
474
0
            } else if (type_and_name[0] == "timer_gauge") {
475
0
                scanner_counter =
476
0
                        ADD_CHILD_TIMER(_profile, type_and_name[1], _connector_name.c_str());
477
0
                COUNTER_SET(scanner_counter, metric_value);
478
0
            } else if (type_and_name[0] == "gauge") {
479
0
                scanner_counter = ADD_CHILD_COUNTER(_profile, type_and_name[1], TUnit::UNIT,
480
0
                                                    _connector_name.c_str());
481
0
                COUNTER_SET(scanner_counter, metric_value);
482
0
            } else if (type_and_name[0] == "bytes_gauge") {
483
0
                scanner_counter = ADD_CHILD_COUNTER(_profile, type_and_name[1], TUnit::BYTES,
484
0
                                                    _connector_name.c_str());
485
0
                COUNTER_SET(scanner_counter, metric_value);
486
0
            } else if (type_and_name[0] == "timer_peak") {
487
0
                auto* scanner_peak_counter = _profile->add_conditition_counter(
488
0
                        type_and_name[1], TUnit::TIME_NS, update_peak, _connector_name.c_str());
489
0
                scanner_peak_counter->conditional_update(metric_value, metric_value);
490
0
            } else if (type_and_name[0] == "peak") {
491
0
                auto* scanner_peak_counter = _profile->add_conditition_counter(
492
0
                        type_and_name[1], TUnit::UNIT, update_peak, _connector_name.c_str());
493
0
                scanner_peak_counter->conditional_update(metric_value, metric_value);
494
0
            } else if (type_and_name[0] == "bytes_peak") {
495
0
                auto* scanner_peak_counter = _profile->add_conditition_counter(
496
0
                        type_and_name[1], TUnit::BYTES, update_peak, _connector_name.c_str());
497
0
                scanner_peak_counter->conditional_update(metric_value, metric_value);
498
0
            } else {
499
0
                LOG(WARNING) << "Type of JNI Scanner metric should be timer, counter, bytes, "
500
0
                             << "timer_gauge, gauge, bytes_gauge, timer_peak, peak or bytes_peak";
501
0
                continue;
502
0
            }
503
4
        }
504
2
    }
505
2
}
506
507
// =========================================================================
508
// MockJniReader
509
// =========================================================================
510
511
MockJniReader::MockJniReader(const std::vector<SlotDescriptor*>& file_slot_descs,
512
                             RuntimeState* state, RuntimeProfile* profile)
513
0
        : JniReader(
514
0
                  file_slot_descs, state, profile, "org/apache/doris/common/jni/MockJniScanner",
515
0
                  [&]() {
516
0
                      std::ostringstream required_fields;
517
0
                      std::ostringstream columns_types;
518
0
                      int index = 0;
519
0
                      for (const auto& desc : file_slot_descs) {
520
0
                          std::string field = desc->col_name();
521
0
                          std::string type =
522
0
                                  JniDataBridge::get_jni_type_with_different_string(desc->type());
523
0
                          if (index == 0) {
524
0
                              required_fields << field;
525
0
                              columns_types << type;
526
0
                          } else {
527
0
                              required_fields << "," << field;
528
0
                              columns_types << "#" << type;
529
0
                          }
530
0
                          index++;
531
0
                      }
532
0
                      return std::map<String, String> {{"mock_rows", "10240"},
533
0
                                                       {"required_fields", required_fields.str()},
534
0
                                                       {"columns_types", columns_types.str()}};
535
0
                  }(),
536
0
                  [&]() {
537
0
                      std::vector<std::string> names;
538
0
                      for (const auto& desc : file_slot_descs) {
539
0
                          names.emplace_back(desc->col_name());
540
0
                      }
541
0
                      return names;
542
0
                  }()) {}
543
544
0
Status MockJniReader::init_reader() {
545
0
    return open(_state, _profile);
546
0
}
547
548
} // namespace doris