Coverage Report

Created: 2026-08-31 16:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/runtime/result_block_buffer.h
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#pragma once
19
20
#include <arrow/type.h>
21
#include <cctz/time_zone.h>
22
#include <gen_cpp/PaloInternalService_types.h>
23
#include <gen_cpp/Types_types.h>
24
25
#include <atomic>
26
#include <condition_variable>
27
#include <cstdint>
28
#include <deque>
29
#include <functional>
30
#include <list>
31
#include <memory>
32
#include <mutex>
33
#include <unordered_map>
34
35
#include "common/status.h"
36
#include "runtime/runtime_state.h"
37
38
namespace google::protobuf {
39
class Closure;
40
} // namespace google::protobuf
41
42
namespace brpc {
43
class Controller;
44
}
45
46
namespace doris {
47
48
class Dependency;
49
50
class GetArrowResultBatchCtx;
51
class Block;
52
53
class PFetchDataResult;
54
55
class ResultBlockBufferBase {
56
public:
57
17
    ResultBlockBufferBase() = default;
58
17
    virtual ~ResultBlockBufferBase() = default;
59
60
    // Close one fragment instance's contribution to this buffer.  When the last
61
    // registered instance calls close(), |is_fully_closed| is set to true,
62
    // indicating that no more producers will write to this buffer and callers may
63
    // safely schedule deferred cleanup.  The buffer is keyed in ResultBufferMgr
64
    // under buffer_id(); use that id (not the per-instance fragment_instance_id)
65
    // when scheduling cancel_at_time() for the deferred cleanup.
66
    virtual Status close(const TUniqueId& id, Status exec_status, int64_t num_rows,
67
                         bool& is_fully_closed) = 0;
68
    virtual void cancel(const Status& reason) = 0;
69
70
    // The id under which this buffer was registered in ResultBufferMgr.
71
    // In parallel result-sink mode this equals query_id; in non-parallel mode
72
    // it equals fragment_instance_id.
73
    [[nodiscard]] virtual const TUniqueId& buffer_id() const = 0;
74
75
    [[nodiscard]] virtual std::shared_ptr<MemTrackerLimiter> mem_tracker() = 0;
76
    virtual void set_dependency(const TUniqueId& id,
77
                                std::shared_ptr<Dependency> result_sink_dependency) = 0;
78
    virtual void add_outfile_cleanup(std::function<void()> cleanup) = 0;
79
    virtual void finish_outfile(bool success) = 0;
80
    virtual void release_outfile_cleanup() = 0;
81
};
82
83
// This is used to serialize a result block by normal queries / arrow flight queries / point queries.
84
template <typename ResultCtxType>
85
class ResultBlockBuffer : public ResultBlockBufferBase {
86
public:
87
    using InBlockType = typename ResultCtxType::ResultType;
88
    ResultBlockBuffer(TUniqueId id, RuntimeState* state, int buffer_size);
89
17
    ~ResultBlockBuffer() override = default;
_ZN5doris17ResultBlockBufferINS_17GetResultBatchCtxEED2Ev
Line
Count
Source
89
12
    ~ResultBlockBuffer() override = default;
_ZN5doris17ResultBlockBufferINS_22GetArrowResultBatchCtxEED2Ev
Line
Count
Source
89
5
    ~ResultBlockBuffer() override = default;
90
91
    Status add_batch(RuntimeState* state, std::shared_ptr<InBlockType>& result);
92
    Status get_batch(std::shared_ptr<ResultCtxType> ctx);
93
    Status close(const TUniqueId& id, Status exec_status, int64_t num_rows,
94
                 bool& is_fully_closed) override;
95
    void cancel(const Status& reason) override;
96
97
0
    [[nodiscard]] const TUniqueId& buffer_id() const override { return _fragment_id; }
Unexecuted instantiation: _ZNK5doris17ResultBlockBufferINS_17GetResultBatchCtxEE9buffer_idEv
Unexecuted instantiation: _ZNK5doris17ResultBlockBufferINS_22GetArrowResultBatchCtxEE9buffer_idEv
98
0
    [[nodiscard]] std::shared_ptr<MemTrackerLimiter> mem_tracker() override { return _mem_tracker; }
Unexecuted instantiation: _ZN5doris17ResultBlockBufferINS_17GetResultBatchCtxEE11mem_trackerEv
Unexecuted instantiation: _ZN5doris17ResultBlockBufferINS_22GetArrowResultBatchCtxEE11mem_trackerEv
99
    void set_dependency(const TUniqueId& id,
100
                        std::shared_ptr<Dependency> result_sink_dependency) override;
101
    void add_outfile_cleanup(std::function<void()> cleanup) override;
102
    void finish_outfile(bool success) override;
103
    void release_outfile_cleanup() override;
104
105
protected:
106
    friend class GetArrowResultBatchCtx;
107
    ResultBlockBuffer(RuntimeState* state)
108
2
            : ResultBlockBuffer<ResultCtxType>(TUniqueId(), state, 0) {}
_ZN5doris17ResultBlockBufferINS_17GetResultBatchCtxEEC2EPNS_12RuntimeStateE
Line
Count
Source
108
2
            : ResultBlockBuffer<ResultCtxType>(TUniqueId(), state, 0) {}
Unexecuted instantiation: _ZN5doris17ResultBlockBufferINS_22GetArrowResultBatchCtxEEC2EPNS_12RuntimeStateE
109
    void _update_dependency();
110
111
    using ResultQueue = std::list<std::shared_ptr<InBlockType>>;
112
113
    // result's query id
114
    TUniqueId _fragment_id;
115
    bool _is_close;
116
    Status _status;
117
    // Producer. blocking queue for result batch waiting to sent to FE by _waiting_rpc.
118
    ResultQueue _result_batch_queue;
119
    // protects all subsequent data in this block
120
    std::mutex _lock;
121
122
    // The last batch size in bytes.
123
    // Determine whether to merge multiple batches based on the size of each batch to avoid getting an excessively large batch after merging.
124
    size_t _last_batch_bytes = 0;
125
126
    // get arrow flight result is a sync method, need wait for data ready and return result.
127
    // TODO, waiting for data will block pipeline, so use a request pool to save requests waiting for data.
128
    std::condition_variable _arrow_data_arrival;
129
    // Consumer. RPCs which FE waiting for result. when _fe_result_batch_queue filled, the rpc could be sent.
130
    std::deque<std::shared_ptr<ResultCtxType>> _waiting_rpc;
131
132
    std::atomic<int64_t> _returned_rows = 0;
133
    // instance id to dependency
134
    std::unordered_map<TUniqueId, std::shared_ptr<Dependency>> _result_sink_dependencies;
135
    std::unordered_map<TUniqueId, size_t> _instance_rows;
136
    std::list<std::unordered_map<TUniqueId, size_t>> _instance_rows_in_queue;
137
    std::shared_ptr<MemTrackerLimiter> _mem_tracker;
138
    int _packet_num = 0;
139
    const int _batch_size;
140
    const std::string _timezone;
141
    const int _be_exec_version;
142
    const segment_v2::CompressionTypePB _fragment_transmission_compression_type;
143
    const int _buffer_limit;
144
145
    enum class OutfileState : uint8_t { PENDING, COMMITTED, ABORTED };
146
    OutfileState _outfile_state = OutfileState::PENDING;
147
    std::vector<std::function<void()>> _outfile_cleanups;
148
};
149
150
} // namespace doris