Coverage Report

Created: 2026-04-15 18:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/runtime/result_block_buffer.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 "runtime/result_block_buffer.h"
19
20
#include <gen_cpp/Data_types.h>
21
#include <gen_cpp/PaloInternalService_types.h>
22
#include <gen_cpp/internal_service.pb.h>
23
#include <glog/logging.h>
24
#include <google/protobuf/stubs/callback.h>
25
// IWYU pragma: no_include <bits/chrono.h>
26
#include <chrono> // IWYU pragma: keep
27
#include <limits>
28
#include <ostream>
29
#include <string>
30
#include <utility>
31
#include <vector>
32
33
#include "arrow/type_fwd.h"
34
#include "common/config.h"
35
#include "core/block/block.h"
36
#include "exec/pipeline/dependency.h"
37
#include "exec/sink/writer/varrow_flight_result_writer.h"
38
#include "exec/sink/writer/vmysql_result_writer.h"
39
#include "runtime/runtime_profile.h"
40
#include "runtime/thread_context.h"
41
#include "util/thrift_util.h"
42
43
namespace doris {
44
45
template <typename ResultCtxType>
46
ResultBlockBuffer<ResultCtxType>::ResultBlockBuffer(TUniqueId id, RuntimeState* state,
47
                                                    int buffer_size)
48
26
        : _fragment_id(std::move(id)),
49
26
          _is_close(false),
50
26
          _batch_size(state->batch_size()),
51
26
          _timezone(state->timezone()),
52
26
          _be_exec_version(state->be_exec_version()),
53
26
          _fragment_transmission_compression_type(state->fragement_transmission_compression_type()),
54
26
          _buffer_limit(buffer_size) {
55
26
    _mem_tracker = MemTrackerLimiter::create_shared(
56
26
            MemTrackerLimiter::Type::QUERY,
57
26
            fmt::format("ResultBlockBuffer#FragmentInstanceId={}", print_id(_fragment_id)));
58
26
}
_ZN5doris17ResultBlockBufferINS_22GetArrowResultBatchCtxEEC2ENS_9TUniqueIdEPNS_12RuntimeStateEi
Line
Count
Source
48
10
        : _fragment_id(std::move(id)),
49
10
          _is_close(false),
50
10
          _batch_size(state->batch_size()),
51
10
          _timezone(state->timezone()),
52
10
          _be_exec_version(state->be_exec_version()),
53
10
          _fragment_transmission_compression_type(state->fragement_transmission_compression_type()),
54
10
          _buffer_limit(buffer_size) {
55
10
    _mem_tracker = MemTrackerLimiter::create_shared(
56
10
            MemTrackerLimiter::Type::QUERY,
57
10
            fmt::format("ResultBlockBuffer#FragmentInstanceId={}", print_id(_fragment_id)));
58
10
}
_ZN5doris17ResultBlockBufferINS_17GetResultBatchCtxEEC2ENS_9TUniqueIdEPNS_12RuntimeStateEi
Line
Count
Source
48
16
        : _fragment_id(std::move(id)),
49
16
          _is_close(false),
50
16
          _batch_size(state->batch_size()),
51
16
          _timezone(state->timezone()),
52
16
          _be_exec_version(state->be_exec_version()),
53
16
          _fragment_transmission_compression_type(state->fragement_transmission_compression_type()),
54
16
          _buffer_limit(buffer_size) {
55
16
    _mem_tracker = MemTrackerLimiter::create_shared(
56
16
            MemTrackerLimiter::Type::QUERY,
57
16
            fmt::format("ResultBlockBuffer#FragmentInstanceId={}", print_id(_fragment_id)));
58
16
}
59
60
template <typename ResultCtxType>
61
Status ResultBlockBuffer<ResultCtxType>::close(const TUniqueId& id, Status exec_status,
62
12
                                               int64_t num_rows, bool& is_fully_closed) {
63
12
    std::unique_lock<std::mutex> l(_lock);
64
12
    _returned_rows.fetch_add(num_rows);
65
    // close will be called multiple times and error status needs to be collected.
66
12
    if (!exec_status.ok()) {
67
8
        _status = exec_status;
68
8
    }
69
70
12
    auto it = _result_sink_dependencies.find(id);
71
12
    if (it != _result_sink_dependencies.end()) {
72
8
        it->second->set_always_ready();
73
8
        _result_sink_dependencies.erase(it);
74
8
    } else {
75
4
        _status = Status::InternalError("Instance {} is not found in ResultBlockBuffer",
76
4
                                        print_id(id));
77
4
    }
78
12
    if (!_result_sink_dependencies.empty()) {
79
        // Still waiting for other instances to finish; this is not the final close.
80
4
        is_fully_closed = false;
81
4
        return _status;
82
4
    }
83
84
    // All instances have closed: the buffer is now fully closed.
85
8
    is_fully_closed = true;
86
8
    _is_close = true;
87
8
    _arrow_data_arrival.notify_all();
88
89
8
    if (!_waiting_rpc.empty()) {
90
8
        if (_status.ok()) {
91
4
            for (auto& ctx : _waiting_rpc) {
92
4
                ctx->on_close(_packet_num, _returned_rows);
93
4
            }
94
4
        } else {
95
4
            for (auto& ctx : _waiting_rpc) {
96
4
                ctx->on_failure(_status);
97
4
            }
98
4
        }
99
8
        _waiting_rpc.clear();
100
8
    }
101
102
8
    return _status;
103
12
}
_ZN5doris17ResultBlockBufferINS_22GetArrowResultBatchCtxEE5closeERKNS_9TUniqueIdENS_6StatusElRb
Line
Count
Source
62
6
                                               int64_t num_rows, bool& is_fully_closed) {
63
6
    std::unique_lock<std::mutex> l(_lock);
64
6
    _returned_rows.fetch_add(num_rows);
65
    // close will be called multiple times and error status needs to be collected.
66
6
    if (!exec_status.ok()) {
67
4
        _status = exec_status;
68
4
    }
69
70
6
    auto it = _result_sink_dependencies.find(id);
71
6
    if (it != _result_sink_dependencies.end()) {
72
4
        it->second->set_always_ready();
73
4
        _result_sink_dependencies.erase(it);
74
4
    } else {
75
2
        _status = Status::InternalError("Instance {} is not found in ResultBlockBuffer",
76
2
                                        print_id(id));
77
2
    }
78
6
    if (!_result_sink_dependencies.empty()) {
79
        // Still waiting for other instances to finish; this is not the final close.
80
2
        is_fully_closed = false;
81
2
        return _status;
82
2
    }
83
84
    // All instances have closed: the buffer is now fully closed.
85
4
    is_fully_closed = true;
86
4
    _is_close = true;
87
4
    _arrow_data_arrival.notify_all();
88
89
4
    if (!_waiting_rpc.empty()) {
90
4
        if (_status.ok()) {
91
2
            for (auto& ctx : _waiting_rpc) {
92
2
                ctx->on_close(_packet_num, _returned_rows);
93
2
            }
94
2
        } else {
95
2
            for (auto& ctx : _waiting_rpc) {
96
2
                ctx->on_failure(_status);
97
2
            }
98
2
        }
99
4
        _waiting_rpc.clear();
100
4
    }
101
102
4
    return _status;
103
6
}
_ZN5doris17ResultBlockBufferINS_17GetResultBatchCtxEE5closeERKNS_9TUniqueIdENS_6StatusElRb
Line
Count
Source
62
6
                                               int64_t num_rows, bool& is_fully_closed) {
63
6
    std::unique_lock<std::mutex> l(_lock);
64
6
    _returned_rows.fetch_add(num_rows);
65
    // close will be called multiple times and error status needs to be collected.
66
6
    if (!exec_status.ok()) {
67
4
        _status = exec_status;
68
4
    }
69
70
6
    auto it = _result_sink_dependencies.find(id);
71
6
    if (it != _result_sink_dependencies.end()) {
72
4
        it->second->set_always_ready();
73
4
        _result_sink_dependencies.erase(it);
74
4
    } else {
75
2
        _status = Status::InternalError("Instance {} is not found in ResultBlockBuffer",
76
2
                                        print_id(id));
77
2
    }
78
6
    if (!_result_sink_dependencies.empty()) {
79
        // Still waiting for other instances to finish; this is not the final close.
80
2
        is_fully_closed = false;
81
2
        return _status;
82
2
    }
83
84
    // All instances have closed: the buffer is now fully closed.
85
4
    is_fully_closed = true;
86
4
    _is_close = true;
87
4
    _arrow_data_arrival.notify_all();
88
89
4
    if (!_waiting_rpc.empty()) {
90
4
        if (_status.ok()) {
91
2
            for (auto& ctx : _waiting_rpc) {
92
2
                ctx->on_close(_packet_num, _returned_rows);
93
2
            }
94
2
        } else {
95
2
            for (auto& ctx : _waiting_rpc) {
96
2
                ctx->on_failure(_status);
97
2
            }
98
2
        }
99
4
        _waiting_rpc.clear();
100
4
    }
101
102
4
    return _status;
103
6
}
104
105
template <typename ResultCtxType>
106
6
void ResultBlockBuffer<ResultCtxType>::cancel(const Status& reason) {
107
6
    std::unique_lock<std::mutex> l(_lock);
108
6
    SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER(_mem_tracker);
109
6
    if (_status.ok()) {
110
6
        _status = reason;
111
6
    }
112
6
    _arrow_data_arrival.notify_all();
113
6
    for (auto& ctx : _waiting_rpc) {
114
4
        ctx->on_failure(reason);
115
4
    }
116
6
    _waiting_rpc.clear();
117
6
    _update_dependency();
118
6
    _result_batch_queue.clear();
119
6
}
_ZN5doris17ResultBlockBufferINS_22GetArrowResultBatchCtxEE6cancelERKNS_6StatusE
Line
Count
Source
106
2
void ResultBlockBuffer<ResultCtxType>::cancel(const Status& reason) {
107
2
    std::unique_lock<std::mutex> l(_lock);
108
2
    SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER(_mem_tracker);
109
2
    if (_status.ok()) {
110
2
        _status = reason;
111
2
    }
112
2
    _arrow_data_arrival.notify_all();
113
2
    for (auto& ctx : _waiting_rpc) {
114
2
        ctx->on_failure(reason);
115
2
    }
116
2
    _waiting_rpc.clear();
117
2
    _update_dependency();
118
2
    _result_batch_queue.clear();
119
2
}
_ZN5doris17ResultBlockBufferINS_17GetResultBatchCtxEE6cancelERKNS_6StatusE
Line
Count
Source
106
4
void ResultBlockBuffer<ResultCtxType>::cancel(const Status& reason) {
107
4
    std::unique_lock<std::mutex> l(_lock);
108
4
    SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER(_mem_tracker);
109
4
    if (_status.ok()) {
110
4
        _status = reason;
111
4
    }
112
4
    _arrow_data_arrival.notify_all();
113
4
    for (auto& ctx : _waiting_rpc) {
114
2
        ctx->on_failure(reason);
115
2
    }
116
4
    _waiting_rpc.clear();
117
4
    _update_dependency();
118
4
    _result_batch_queue.clear();
119
4
}
120
121
template <typename ResultCtxType>
122
void ResultBlockBuffer<ResultCtxType>::set_dependency(
123
18
        const TUniqueId& id, std::shared_ptr<Dependency> result_sink_dependency) {
124
18
    std::unique_lock<std::mutex> l(_lock);
125
18
    _result_sink_dependencies[id] = result_sink_dependency;
126
18
    _update_dependency();
127
18
}
_ZN5doris17ResultBlockBufferINS_22GetArrowResultBatchCtxEE14set_dependencyERKNS_9TUniqueIdESt10shared_ptrINS_10DependencyEE
Line
Count
Source
123
10
        const TUniqueId& id, std::shared_ptr<Dependency> result_sink_dependency) {
124
10
    std::unique_lock<std::mutex> l(_lock);
125
10
    _result_sink_dependencies[id] = result_sink_dependency;
126
10
    _update_dependency();
127
10
}
_ZN5doris17ResultBlockBufferINS_17GetResultBatchCtxEE14set_dependencyERKNS_9TUniqueIdESt10shared_ptrINS_10DependencyEE
Line
Count
Source
123
8
        const TUniqueId& id, std::shared_ptr<Dependency> result_sink_dependency) {
124
8
    std::unique_lock<std::mutex> l(_lock);
125
8
    _result_sink_dependencies[id] = result_sink_dependency;
126
8
    _update_dependency();
127
8
}
128
129
template <typename ResultCtxType>
130
72
void ResultBlockBuffer<ResultCtxType>::_update_dependency() {
131
72
    if (!_status.ok()) {
132
14
        for (auto it : _result_sink_dependencies) {
133
12
            it.second->set_ready();
134
12
        }
135
14
        return;
136
14
    }
137
138
58
    for (auto it : _result_sink_dependencies) {
139
52
        if (_instance_rows[it.first] > _batch_size) {
140
12
            it.second->block();
141
40
        } else {
142
40
            it.second->set_ready();
143
40
        }
144
52
    }
145
58
}
_ZN5doris17ResultBlockBufferINS_22GetArrowResultBatchCtxEE18_update_dependencyEv
Line
Count
Source
130
38
void ResultBlockBuffer<ResultCtxType>::_update_dependency() {
131
38
    if (!_status.ok()) {
132
6
        for (auto it : _result_sink_dependencies) {
133
6
            it.second->set_ready();
134
6
        }
135
6
        return;
136
6
    }
137
138
32
    for (auto it : _result_sink_dependencies) {
139
30
        if (_instance_rows[it.first] > _batch_size) {
140
8
            it.second->block();
141
22
        } else {
142
22
            it.second->set_ready();
143
22
        }
144
30
    }
145
32
}
_ZN5doris17ResultBlockBufferINS_17GetResultBatchCtxEE18_update_dependencyEv
Line
Count
Source
130
34
void ResultBlockBuffer<ResultCtxType>::_update_dependency() {
131
34
    if (!_status.ok()) {
132
8
        for (auto it : _result_sink_dependencies) {
133
6
            it.second->set_ready();
134
6
        }
135
8
        return;
136
8
    }
137
138
26
    for (auto it : _result_sink_dependencies) {
139
22
        if (_instance_rows[it.first] > _batch_size) {
140
4
            it.second->block();
141
18
        } else {
142
18
            it.second->set_ready();
143
18
        }
144
22
    }
145
26
}
146
147
template <typename ResultCtxType>
148
30
Status ResultBlockBuffer<ResultCtxType>::get_batch(std::shared_ptr<ResultCtxType> ctx) {
149
30
    std::lock_guard<std::mutex> l(_lock);
150
30
    SCOPED_ATTACH_TASK(_mem_tracker);
151
30
    Defer defer {[&]() { _update_dependency(); }};
_ZZN5doris17ResultBlockBufferINS_22GetArrowResultBatchCtxEE9get_batchESt10shared_ptrIS1_EENKUlvE_clEv
Line
Count
Source
151
16
    Defer defer {[&]() { _update_dependency(); }};
_ZZN5doris17ResultBlockBufferINS_17GetResultBatchCtxEE9get_batchESt10shared_ptrIS1_EENKUlvE_clEv
Line
Count
Source
151
14
    Defer defer {[&]() { _update_dependency(); }};
152
30
    if (!_status.ok()) {
153
4
        ctx->on_failure(_status);
154
4
        return _status;
155
4
    }
156
26
    if (!_result_batch_queue.empty()) {
157
6
        auto result = _result_batch_queue.front();
158
6
        _result_batch_queue.pop_front();
159
6
        for (auto it : _instance_rows_in_queue.front()) {
160
6
            _instance_rows[it.first] -= it.second;
161
6
        }
162
6
        _instance_rows_in_queue.pop_front();
163
6
        RETURN_IF_ERROR(ctx->on_data(result, _packet_num, this));
164
6
        _packet_num++;
165
6
        return Status::OK();
166
6
    }
167
20
    if (_is_close) {
168
4
        if (!_status.ok()) {
169
0
            ctx->on_failure(_status);
170
0
            return Status::OK();
171
0
        }
172
4
        ctx->on_close(_packet_num, _returned_rows);
173
4
        LOG(INFO) << fmt::format(
174
4
                "ResultBlockBuffer finished, fragment_id={}, is_close={}, is_cancelled={}, "
175
4
                "packet_num={}, peak_memory_usage={}",
176
4
                print_id(_fragment_id), _is_close, !_status.ok(), _packet_num,
177
4
                _mem_tracker->peak_consumption());
178
4
        return Status::OK();
179
4
    }
180
    // no ready data, push ctx to waiting list
181
16
    _waiting_rpc.push_back(ctx);
182
16
    return Status::OK();
183
20
}
_ZN5doris17ResultBlockBufferINS_22GetArrowResultBatchCtxEE9get_batchESt10shared_ptrIS1_E
Line
Count
Source
148
16
Status ResultBlockBuffer<ResultCtxType>::get_batch(std::shared_ptr<ResultCtxType> ctx) {
149
16
    std::lock_guard<std::mutex> l(_lock);
150
16
    SCOPED_ATTACH_TASK(_mem_tracker);
151
16
    Defer defer {[&]() { _update_dependency(); }};
152
16
    if (!_status.ok()) {
153
2
        ctx->on_failure(_status);
154
2
        return _status;
155
2
    }
156
14
    if (!_result_batch_queue.empty()) {
157
4
        auto result = _result_batch_queue.front();
158
4
        _result_batch_queue.pop_front();
159
4
        for (auto it : _instance_rows_in_queue.front()) {
160
4
            _instance_rows[it.first] -= it.second;
161
4
        }
162
4
        _instance_rows_in_queue.pop_front();
163
4
        RETURN_IF_ERROR(ctx->on_data(result, _packet_num, this));
164
4
        _packet_num++;
165
4
        return Status::OK();
166
4
    }
167
10
    if (_is_close) {
168
2
        if (!_status.ok()) {
169
0
            ctx->on_failure(_status);
170
0
            return Status::OK();
171
0
        }
172
2
        ctx->on_close(_packet_num, _returned_rows);
173
2
        LOG(INFO) << fmt::format(
174
2
                "ResultBlockBuffer finished, fragment_id={}, is_close={}, is_cancelled={}, "
175
2
                "packet_num={}, peak_memory_usage={}",
176
2
                print_id(_fragment_id), _is_close, !_status.ok(), _packet_num,
177
2
                _mem_tracker->peak_consumption());
178
2
        return Status::OK();
179
2
    }
180
    // no ready data, push ctx to waiting list
181
8
    _waiting_rpc.push_back(ctx);
182
8
    return Status::OK();
183
10
}
_ZN5doris17ResultBlockBufferINS_17GetResultBatchCtxEE9get_batchESt10shared_ptrIS1_E
Line
Count
Source
148
14
Status ResultBlockBuffer<ResultCtxType>::get_batch(std::shared_ptr<ResultCtxType> ctx) {
149
14
    std::lock_guard<std::mutex> l(_lock);
150
14
    SCOPED_ATTACH_TASK(_mem_tracker);
151
14
    Defer defer {[&]() { _update_dependency(); }};
152
14
    if (!_status.ok()) {
153
2
        ctx->on_failure(_status);
154
2
        return _status;
155
2
    }
156
12
    if (!_result_batch_queue.empty()) {
157
2
        auto result = _result_batch_queue.front();
158
2
        _result_batch_queue.pop_front();
159
2
        for (auto it : _instance_rows_in_queue.front()) {
160
2
            _instance_rows[it.first] -= it.second;
161
2
        }
162
2
        _instance_rows_in_queue.pop_front();
163
2
        RETURN_IF_ERROR(ctx->on_data(result, _packet_num, this));
164
2
        _packet_num++;
165
2
        return Status::OK();
166
2
    }
167
10
    if (_is_close) {
168
2
        if (!_status.ok()) {
169
0
            ctx->on_failure(_status);
170
0
            return Status::OK();
171
0
        }
172
2
        ctx->on_close(_packet_num, _returned_rows);
173
2
        LOG(INFO) << fmt::format(
174
2
                "ResultBlockBuffer finished, fragment_id={}, is_close={}, is_cancelled={}, "
175
2
                "packet_num={}, peak_memory_usage={}",
176
2
                print_id(_fragment_id), _is_close, !_status.ok(), _packet_num,
177
2
                _mem_tracker->peak_consumption());
178
2
        return Status::OK();
179
2
    }
180
    // no ready data, push ctx to waiting list
181
8
    _waiting_rpc.push_back(ctx);
182
8
    return Status::OK();
183
10
}
184
185
template <typename ResultCtxType>
186
Status ResultBlockBuffer<ResultCtxType>::add_batch(RuntimeState* state,
187
22
                                                   std::shared_ptr<InBlockType>& result) {
188
22
    std::unique_lock<std::mutex> l(_lock);
189
190
22
    if (!_status.ok()) {
191
4
        return _status;
192
4
    }
193
194
18
    if (_waiting_rpc.empty()) {
195
14
        auto sz = 0;
196
14
        auto num_rows = 0;
197
14
        size_t batch_size = 0;
198
14
        if constexpr (std::is_same_v<InBlockType, Block>) {
199
8
            num_rows = cast_set<int>(result->rows());
200
8
            batch_size = result->bytes();
201
8
        } else if constexpr (std::is_same_v<InBlockType, TFetchDataResult>) {
202
6
            num_rows = cast_set<int>(result->result_batch.rows.size());
203
22
            for (const auto& row : result->result_batch.rows) {
204
22
                batch_size += row.size();
205
22
            }
206
6
        }
207
14
        if (!_result_batch_queue.empty()) {
208
6
            if constexpr (std::is_same_v<InBlockType, Block>) {
209
4
                sz = cast_set<int>(_result_batch_queue.back()->rows());
210
4
            } else if constexpr (std::is_same_v<InBlockType, TFetchDataResult>) {
211
2
                sz = cast_set<int>(_result_batch_queue.back()->result_batch.rows.size());
212
2
            }
213
6
            if (sz + num_rows < _buffer_limit &&
214
6
                (batch_size + _last_batch_bytes) <= config::thrift_max_message_size) {
215
6
                if constexpr (std::is_same_v<InBlockType, Block>) {
216
4
                    auto last_block = _result_batch_queue.back();
217
8
                    for (size_t i = 0; i < last_block->columns(); i++) {
218
4
                        last_block->mutate_columns()[i]->insert_range_from(
219
4
                                *result->get_by_position(i).column, 0, num_rows);
220
4
                    }
221
4
                } else {
222
2
                    std::vector<std::string>& back_rows =
223
2
                            _result_batch_queue.back()->result_batch.rows;
224
2
                    std::vector<std::string>& result_rows = result->result_batch.rows;
225
2
                    back_rows.insert(back_rows.end(), std::make_move_iterator(result_rows.begin()),
226
2
                                     std::make_move_iterator(result_rows.end()));
227
2
                }
228
6
                _last_batch_bytes += batch_size;
229
6
            } else {
230
0
                _instance_rows_in_queue.emplace_back();
231
0
                _result_batch_queue.push_back(std::move(result));
232
0
                _last_batch_bytes = batch_size;
233
0
                _arrow_data_arrival
234
0
                        .notify_one(); // Only valid for get_arrow_batch(std::shared_ptr<Block>,)
235
0
            }
236
8
        } else {
237
8
            _instance_rows_in_queue.emplace_back();
238
8
            _result_batch_queue.push_back(std::move(result));
239
8
            _last_batch_bytes = batch_size;
240
8
            _arrow_data_arrival
241
8
                    .notify_one(); // Only valid for get_arrow_batch(std::shared_ptr<Block>,)
242
8
        }
243
14
        _instance_rows[state->fragment_instance_id()] += num_rows;
244
14
        _instance_rows_in_queue.back()[state->fragment_instance_id()] += num_rows;
245
14
    } else {
246
4
        auto ctx = _waiting_rpc.front();
247
4
        _waiting_rpc.pop_front();
248
4
        RETURN_IF_ERROR(ctx->on_data(result, _packet_num, this));
249
4
        _packet_num++;
250
4
    }
251
252
18
    _update_dependency();
253
18
    return Status::OK();
254
18
}
_ZN5doris17ResultBlockBufferINS_22GetArrowResultBatchCtxEE9add_batchEPNS_12RuntimeStateERSt10shared_ptrINS_5BlockEE
Line
Count
Source
187
12
                                                   std::shared_ptr<InBlockType>& result) {
188
12
    std::unique_lock<std::mutex> l(_lock);
189
190
12
    if (!_status.ok()) {
191
2
        return _status;
192
2
    }
193
194
10
    if (_waiting_rpc.empty()) {
195
8
        auto sz = 0;
196
8
        auto num_rows = 0;
197
8
        size_t batch_size = 0;
198
8
        if constexpr (std::is_same_v<InBlockType, Block>) {
199
8
            num_rows = cast_set<int>(result->rows());
200
8
            batch_size = result->bytes();
201
        } else if constexpr (std::is_same_v<InBlockType, TFetchDataResult>) {
202
            num_rows = cast_set<int>(result->result_batch.rows.size());
203
            for (const auto& row : result->result_batch.rows) {
204
                batch_size += row.size();
205
            }
206
        }
207
8
        if (!_result_batch_queue.empty()) {
208
4
            if constexpr (std::is_same_v<InBlockType, Block>) {
209
4
                sz = cast_set<int>(_result_batch_queue.back()->rows());
210
            } else if constexpr (std::is_same_v<InBlockType, TFetchDataResult>) {
211
                sz = cast_set<int>(_result_batch_queue.back()->result_batch.rows.size());
212
            }
213
4
            if (sz + num_rows < _buffer_limit &&
214
4
                (batch_size + _last_batch_bytes) <= config::thrift_max_message_size) {
215
4
                if constexpr (std::is_same_v<InBlockType, Block>) {
216
4
                    auto last_block = _result_batch_queue.back();
217
8
                    for (size_t i = 0; i < last_block->columns(); i++) {
218
4
                        last_block->mutate_columns()[i]->insert_range_from(
219
4
                                *result->get_by_position(i).column, 0, num_rows);
220
4
                    }
221
                } else {
222
                    std::vector<std::string>& back_rows =
223
                            _result_batch_queue.back()->result_batch.rows;
224
                    std::vector<std::string>& result_rows = result->result_batch.rows;
225
                    back_rows.insert(back_rows.end(), std::make_move_iterator(result_rows.begin()),
226
                                     std::make_move_iterator(result_rows.end()));
227
                }
228
4
                _last_batch_bytes += batch_size;
229
4
            } else {
230
0
                _instance_rows_in_queue.emplace_back();
231
0
                _result_batch_queue.push_back(std::move(result));
232
0
                _last_batch_bytes = batch_size;
233
0
                _arrow_data_arrival
234
0
                        .notify_one(); // Only valid for get_arrow_batch(std::shared_ptr<Block>,)
235
0
            }
236
4
        } else {
237
4
            _instance_rows_in_queue.emplace_back();
238
4
            _result_batch_queue.push_back(std::move(result));
239
4
            _last_batch_bytes = batch_size;
240
4
            _arrow_data_arrival
241
4
                    .notify_one(); // Only valid for get_arrow_batch(std::shared_ptr<Block>,)
242
4
        }
243
8
        _instance_rows[state->fragment_instance_id()] += num_rows;
244
8
        _instance_rows_in_queue.back()[state->fragment_instance_id()] += num_rows;
245
8
    } else {
246
2
        auto ctx = _waiting_rpc.front();
247
2
        _waiting_rpc.pop_front();
248
2
        RETURN_IF_ERROR(ctx->on_data(result, _packet_num, this));
249
2
        _packet_num++;
250
2
    }
251
252
10
    _update_dependency();
253
10
    return Status::OK();
254
10
}
_ZN5doris17ResultBlockBufferINS_17GetResultBatchCtxEE9add_batchEPNS_12RuntimeStateERSt10shared_ptrINS_16TFetchDataResultEE
Line
Count
Source
187
10
                                                   std::shared_ptr<InBlockType>& result) {
188
10
    std::unique_lock<std::mutex> l(_lock);
189
190
10
    if (!_status.ok()) {
191
2
        return _status;
192
2
    }
193
194
8
    if (_waiting_rpc.empty()) {
195
6
        auto sz = 0;
196
6
        auto num_rows = 0;
197
6
        size_t batch_size = 0;
198
        if constexpr (std::is_same_v<InBlockType, Block>) {
199
            num_rows = cast_set<int>(result->rows());
200
            batch_size = result->bytes();
201
6
        } else if constexpr (std::is_same_v<InBlockType, TFetchDataResult>) {
202
6
            num_rows = cast_set<int>(result->result_batch.rows.size());
203
22
            for (const auto& row : result->result_batch.rows) {
204
22
                batch_size += row.size();
205
22
            }
206
6
        }
207
6
        if (!_result_batch_queue.empty()) {
208
            if constexpr (std::is_same_v<InBlockType, Block>) {
209
                sz = cast_set<int>(_result_batch_queue.back()->rows());
210
2
            } else if constexpr (std::is_same_v<InBlockType, TFetchDataResult>) {
211
2
                sz = cast_set<int>(_result_batch_queue.back()->result_batch.rows.size());
212
2
            }
213
2
            if (sz + num_rows < _buffer_limit &&
214
2
                (batch_size + _last_batch_bytes) <= config::thrift_max_message_size) {
215
                if constexpr (std::is_same_v<InBlockType, Block>) {
216
                    auto last_block = _result_batch_queue.back();
217
                    for (size_t i = 0; i < last_block->columns(); i++) {
218
                        last_block->mutate_columns()[i]->insert_range_from(
219
                                *result->get_by_position(i).column, 0, num_rows);
220
                    }
221
2
                } else {
222
2
                    std::vector<std::string>& back_rows =
223
2
                            _result_batch_queue.back()->result_batch.rows;
224
2
                    std::vector<std::string>& result_rows = result->result_batch.rows;
225
2
                    back_rows.insert(back_rows.end(), std::make_move_iterator(result_rows.begin()),
226
2
                                     std::make_move_iterator(result_rows.end()));
227
2
                }
228
2
                _last_batch_bytes += batch_size;
229
2
            } else {
230
0
                _instance_rows_in_queue.emplace_back();
231
0
                _result_batch_queue.push_back(std::move(result));
232
0
                _last_batch_bytes = batch_size;
233
0
                _arrow_data_arrival
234
0
                        .notify_one(); // Only valid for get_arrow_batch(std::shared_ptr<Block>,)
235
0
            }
236
4
        } else {
237
4
            _instance_rows_in_queue.emplace_back();
238
4
            _result_batch_queue.push_back(std::move(result));
239
4
            _last_batch_bytes = batch_size;
240
4
            _arrow_data_arrival
241
4
                    .notify_one(); // Only valid for get_arrow_batch(std::shared_ptr<Block>,)
242
4
        }
243
6
        _instance_rows[state->fragment_instance_id()] += num_rows;
244
6
        _instance_rows_in_queue.back()[state->fragment_instance_id()] += num_rows;
245
6
    } else {
246
2
        auto ctx = _waiting_rpc.front();
247
2
        _waiting_rpc.pop_front();
248
2
        RETURN_IF_ERROR(ctx->on_data(result, _packet_num, this));
249
2
        _packet_num++;
250
2
    }
251
252
8
    _update_dependency();
253
8
    return Status::OK();
254
8
}
255
256
template class ResultBlockBuffer<GetArrowResultBatchCtx>;
257
template class ResultBlockBuffer<GetResultBatchCtx>;
258
259
} // namespace doris