Coverage Report

Created: 2026-08-14 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/load/channel/load_channel.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 <gen_cpp/internal_service.pb.h>
21
22
#include <atomic>
23
#include <cstdint>
24
#include <memory>
25
#include <mutex>
26
#include <ostream>
27
#include <string>
28
#include <unordered_map>
29
#include <unordered_set>
30
#include <utility>
31
#include <vector>
32
33
#include "common/status.h"
34
#include "runtime/runtime_profile.h"
35
#include "runtime/workload_group/workload_group_fwd.h"
36
#include "runtime/workload_management/resource_context.h"
37
#include "util/uid_util.h"
38
39
namespace google::protobuf {
40
class Closure;
41
}
42
43
namespace doris {
44
45
class BaseTabletsChannel;
46
class LoadChannelMgr;
47
48
// A LoadChannel manages tablets channels for all indexes
49
// corresponding to a certain load job
50
class LoadChannel {
51
public:
52
    struct FinalTabletResult {
53
        PTabletWriterAddBlockResult result;
54
        int32_t owner_sender_id = -1;
55
    };
56
57
    LoadChannel(const UniqueId& load_id, int64_t timeout_s, bool is_high_priority,
58
                std::string sender_ip, int64_t backend_id, bool enable_profile, int64_t wg_id);
59
    ~LoadChannel();
60
61
    // open a new load channel if not exist
62
    Status open(const PTabletWriterOpenRequest& request);
63
64
    // this batch must belong to a index in one transaction
65
    Status add_batch(const PTabletWriterAddBlockRequest& request,
66
                     PTabletWriterAddBlockResult* response,
67
                     google::protobuf::Closure** done = nullptr);
68
69
    // return true if this load channel has been opened and all tablets channels are closed then.
70
    bool is_finished();
71
72
97.8k
    bool need_final_tablet_result() const { return _need_final_tablet_result.load(); }
73
    bool copy_final_tablet_results(std::unordered_map<int64_t, FinalTabletResult>* results,
74
                                   size_t max_bytes, bool* oversized, size_t* result_bytes) const;
75
76
    Status cancel(const Status& reason = Status::Cancelled("Load channel cancelled"));
77
78
246
    time_t last_updated_time() const { return _last_updated_time.load(); }
79
80
0
    const UniqueId& load_id() const { return _load_id; }
81
82
246
    int64_t timeout() const { return _timeout_s; }
83
84
55.0k
    bool is_high_priority() const { return _is_high_priority; }
85
86
54.4k
    bool is_cancelled() const { return _cancelled.load(); }
87
88
54.4k
    WorkloadGroupPtr workload_group() const { return _resource_ctx->workload_group(); }
89
90
55.0k
    RuntimeProfile::Counter* get_mgr_add_batch_timer() { return _mgr_add_batch_timer; }
91
54.4k
    RuntimeProfile::Counter* get_handle_mem_limit_timer() { return _handle_mem_limit_timer; }
92
93
protected:
94
    Status _get_tablets_channel(std::shared_ptr<BaseTabletsChannel>& channel, bool& is_finished,
95
                                int64_t index_id);
96
97
    Status _handle_eos(BaseTabletsChannel* channel, const PTabletWriterAddBlockRequest& request,
98
                       PTabletWriterAddBlockResult* response, bool* finished);
99
100
    void _defer_or_copy_final_tablet_result(int64_t index_id, int32_t sender_id,
101
                                            PTabletWriterAddBlockResult* response,
102
                                            google::protobuf::Closure** done);
103
    void _publish_final_tablet_result(int64_t index_id, int32_t sender_id,
104
                                      const PTabletWriterAddBlockResult& result);
105
    void _cancel_final_tablet_result_waiters(const Status& reason);
106
107
    void _init_profile();
108
    // thread safety
109
    void _report_profile(PTabletWriterAddBlockResult* response);
110
111
private:
112
    friend class LoadChannelMgr;
113
114
    void _reserve_final_tablet_result(int64_t index_id);
115
116
    UniqueId _load_id;
117
    int64_t _txn_id = 0;
118
119
    std::mutex _profile_serialize_lock;
120
    std::unique_ptr<RuntimeProfile> _profile;
121
    RuntimeProfile* _self_profile = nullptr;
122
    RuntimeProfile::Counter* _add_batch_number_counter = nullptr;
123
    RuntimeProfile::Counter* _add_batch_timer = nullptr;
124
    RuntimeProfile::Counter* _add_batch_times = nullptr;
125
    RuntimeProfile::Counter* _mgr_add_batch_timer = nullptr;
126
    RuntimeProfile::Counter* _handle_mem_limit_timer = nullptr;
127
    RuntimeProfile::Counter* _handle_eos_timer = nullptr;
128
129
    // lock protect the tablets channel map
130
    std::mutex _lock;
131
    // index id -> tablets channel
132
    std::unordered_map<int64_t, std::shared_ptr<BaseTabletsChannel>> _tablets_channels;
133
    // index id -> (received rows, filtered rows)
134
    std::unordered_map<int64_t, std::pair<size_t, size_t>> _tablets_channels_rows;
135
    std::mutex _tablets_channels_lock;
136
    // This is to save finished channels id, to handle the retry request.
137
    std::unordered_set<int64_t> _finished_channel_ids;
138
    // set to true if at least one tablets channel has been opened
139
    bool _opened = false;
140
    std::atomic<bool> _cancelled {false};
141
142
    std::shared_ptr<ResourceContext> _resource_ctx;
143
144
    std::atomic<time_t> _last_updated_time;
145
146
    // the timeout of this load job.
147
    // Timed out channels will be periodically deleted by LoadChannelMgr.
148
    int64_t _timeout_s;
149
150
    // true if this is a high priority load task
151
    bool _is_high_priority = false;
152
153
    // the ip where tablet sink locate
154
    std::string _sender_ip;
155
156
    int64_t _backend_id;
157
158
    bool _enable_profile;
159
160
    struct FinalTabletResultWaiter {
161
        PTabletWriterAddBlockResult* response = nullptr;
162
        google::protobuf::Closure* done = nullptr;
163
    };
164
    struct FinalTabletResultState {
165
        std::shared_ptr<PTabletWriterAddBlockResult> tablet_result;
166
        int32_t owner_sender_id = -1;
167
        std::vector<FinalTabletResultWaiter> waiters;
168
        std::unordered_map<int64_t, PTabletError> tablet_errors;
169
    };
170
    mutable std::mutex _final_tablet_result_lock;
171
    std::atomic<bool> _need_final_tablet_result {false};
172
    std::unordered_map<int64_t, FinalTabletResultState> _final_tablet_results;
173
    Status _final_tablet_result_cancel_status;
174
};
175
176
0
inline std::ostream& operator<<(std::ostream& os, LoadChannel& load_channel) {
177
0
    os << "LoadChannel(id=" << load_channel.load_id()
178
0
       << ", last_update_time=" << static_cast<uint64_t>(load_channel.last_updated_time())
179
0
       << ", is high priority: " << load_channel.is_high_priority() << ")";
180
0
    return os;
181
0
}
182
183
} // namespace doris