Coverage Report

Created: 2026-11-02 18:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/service/internal_service.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 "service/internal_service.h"
19
20
#include <assert.h>
21
#include <brpc/closure_guard.h>
22
#include <brpc/controller.h>
23
#include <bthread/bthread.h>
24
#include <bthread/types.h>
25
#include <butil/errno.h>
26
#include <butil/iobuf.h>
27
#include <fcntl.h>
28
#include <fmt/core.h>
29
#include <gen_cpp/DataSinks_types.h>
30
#include <gen_cpp/MasterService_types.h>
31
#include <gen_cpp/PaloInternalService_types.h>
32
#include <gen_cpp/PlanNodes_types.h>
33
#include <gen_cpp/Status_types.h>
34
#include <gen_cpp/Types_types.h>
35
#include <gen_cpp/internal_service.pb.h>
36
#include <gen_cpp/olap_file.pb.h>
37
#include <gen_cpp/segment_v2.pb.h>
38
#include <gen_cpp/types.pb.h>
39
#include <google/protobuf/stubs/callback.h>
40
#include <stddef.h>
41
#include <stdint.h>
42
#include <sys/stat.h>
43
44
#include <algorithm>
45
#include <exception>
46
#include <memory>
47
#include <set>
48
#include <sstream>
49
#include <string>
50
#include <utility>
51
#include <vector>
52
53
#include "cloud/cloud_storage_engine.h"
54
#include "cloud/cloud_tablet_mgr.h"
55
#include "cloud/config.h"
56
#include "common/config.h"
57
#include "common/exception.h"
58
#include "common/logging.h"
59
#include "common/metrics/doris_metrics.h"
60
#include "common/metrics/metrics.h"
61
#include "common/signal_handler.h"
62
#include "common/status.h"
63
#include "core/block/block.h"
64
#include "core/data_type/data_type.h"
65
#include "exec/common/variant_util.h"
66
#include "exec/exchange/vdata_stream_mgr.h"
67
#include "exec/rowid_fetcher.h"
68
#include "exec/runtime_filter/runtime_filter_mgr.h"
69
#include "exec/sink/writer/varrow_flight_result_writer.h"
70
#include "exec/sink/writer/vmysql_result_writer.h"
71
#include "exprs/function/dictionary_factory.h"
72
#include "format/arrow/arrow_row_batch.h"
73
#include "format/jni/jni_reader.h"
74
#include "format_v2/column_data.h"
75
#include "format_v2/schema_reader.h"
76
#include "io/file_factory.h"
77
#include "io/fs/local_file_system.h"
78
#include "io/fs/stream_load_pipe.h"
79
#include "io/io_common.h"
80
#include "load/channel/eos_completion.h"
81
#include "load/channel/load_channel_mgr.h"
82
#include "load/channel/load_stream_mgr.h"
83
#include "load/delta_writer/delta_writer.h"
84
#include "load/group_commit/wal/wal_manager.h"
85
#include "load/routine_load/routine_load_task_executor.h"
86
#include "load/stream_load/new_load_stream_mgr.h"
87
#include "load/stream_load/stream_load_context.h"
88
#include "runtime/cache/result_cache.h"
89
#include "runtime/cdc_client_mgr.h"
90
#include "runtime/descriptors.h"
91
#include "runtime/exec_env.h"
92
#include "runtime/fold_constant_executor.h"
93
#include "runtime/fragment_mgr.h"
94
#include "runtime/query_context.h"
95
#include "runtime/result_block_buffer.h"
96
#include "runtime/result_buffer_mgr.h"
97
#include "runtime/runtime_profile.h"
98
#include "runtime/thread_context.h"
99
#include "runtime/workload_group/workload_group.h"
100
#include "runtime/workload_group/workload_group_manager.h"
101
#include "service/backend_options.h"
102
#include "service/point_query_executor.h"
103
#include "storage/data_dir.h"
104
#include "storage/olap_common.h"
105
#include "storage/olap_define.h"
106
#include "storage/rowset/rowset.h"
107
#include "storage/rowset/rowset_meta.h"
108
#include "storage/segment/column_reader.h"
109
#include "storage/storage_engine.h"
110
#include "storage/tablet/tablet_fwd.h"
111
#include "storage/tablet/tablet_manager.h"
112
#include "storage/tablet/tablet_schema.h"
113
#include "storage/txn/txn_manager.h"
114
#include "util/async_io.h"
115
#include "util/brpc_client_cache.h"
116
#include "util/brpc_closure.h"
117
#include "util/jdbc_utils.h"
118
#include "util/jsonb/serialize.h"
119
#include "util/md5.h"
120
#include "util/network_util.h"
121
#include "util/proto_util.h"
122
#include "util/stopwatch.hpp"
123
#include "util/string_util.h"
124
#include "util/thrift_util.h"
125
#include "util/time.h"
126
#include "util/uid_util.h"
127
128
namespace google {
129
namespace protobuf {
130
class RpcController;
131
} // namespace protobuf
132
} // namespace google
133
134
namespace doris {
135
#include "common/compile_check_avoid_begin.h"
136
using namespace ErrorCode;
137
138
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(load_light_work_pool_queue_size, MetricUnit::NOUNIT);
139
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(load_light_work_active_threads, MetricUnit::NOUNIT);
140
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(load_light_work_pool_max_queue_size, MetricUnit::NOUNIT);
141
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(load_light_work_max_threads, MetricUnit::NOUNIT);
142
143
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(heavy_work_pool_queue_size, MetricUnit::NOUNIT);
144
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(peer_fetch_work_pool_queue_size, MetricUnit::NOUNIT);
145
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(light_work_pool_queue_size, MetricUnit::NOUNIT);
146
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(heavy_work_active_threads, MetricUnit::NOUNIT);
147
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(peer_fetch_work_active_threads, MetricUnit::NOUNIT);
148
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(light_work_active_threads, MetricUnit::NOUNIT);
149
150
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(heavy_work_pool_max_queue_size, MetricUnit::NOUNIT);
151
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(peer_fetch_work_pool_max_queue_size, MetricUnit::NOUNIT);
152
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(light_work_pool_max_queue_size, MetricUnit::NOUNIT);
153
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(heavy_work_max_threads, MetricUnit::NOUNIT);
154
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(peer_fetch_work_max_threads, MetricUnit::NOUNIT);
155
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(light_work_max_threads, MetricUnit::NOUNIT);
156
157
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(arrow_flight_work_pool_queue_size, MetricUnit::NOUNIT);
158
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(arrow_flight_work_active_threads, MetricUnit::NOUNIT);
159
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(arrow_flight_work_pool_max_queue_size, MetricUnit::NOUNIT);
160
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(arrow_flight_work_max_threads, MetricUnit::NOUNIT);
161
162
static bvar::LatencyRecorder g_process_remote_fetch_rowsets_latency("process_remote_fetch_rowsets");
163
164
359
static int32_t resolved_brpc_load_light_work_pool_max_queue_size() {
165
359
    return config::brpc_load_light_work_pool_max_queue_size != -1
166
359
                   ? config::brpc_load_light_work_pool_max_queue_size
167
359
                   : std::max(1024, CpuInfo::num_cores() * 32);
168
359
}
169
170
359
static int32_t resolved_brpc_peer_fetch_pool_threads() {
171
359
    return config::brpc_peer_fetch_pool_threads != -1 ? config::brpc_peer_fetch_pool_threads
172
359
                                                      : std::max(64, CpuInfo::num_cores() * 2);
173
359
}
174
175
359
static int32_t resolved_brpc_peer_fetch_pool_max_queue_size() {
176
359
    return config::brpc_peer_fetch_pool_max_queue_size != -1
177
359
                   ? config::brpc_peer_fetch_pool_max_queue_size
178
359
                   : std::max(4096, CpuInfo::num_cores() * 128);
179
359
}
180
181
template <typename T>
182
concept CanCancel = requires(T* response) { response->mutable_status(); };
183
184
template <typename T>
185
1
void offer_failed(T* response, google::protobuf::Closure* done, const FifoThreadPool& pool) {
186
1
    brpc::ClosureGuard closure_guard(done);
187
1
    LOG(WARNING) << "fail to offer request to the work pool, pool=" << pool.get_info();
188
1
}
_ZN5doris12offer_failedINS_25PTabletWriterCancelResultEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Line
Count
Source
185
1
void offer_failed(T* response, google::protobuf::Closure* done, const FifoThreadPool& pool) {
186
1
    brpc::ClosureGuard closure_guard(done);
187
    LOG(WARNING) << "fail to offer request to the work pool, pool=" << pool.get_info();
188
1
}
Unexecuted instantiation: _ZN5doris12offer_failedINS_14PCacheResponseEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedINS_17PFetchCacheResultEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
189
190
template <CanCancel T>
191
3
void offer_failed(T* response, google::protobuf::Closure* done, const FifoThreadPool& pool) {
192
3
    brpc::ClosureGuard closure_guard(done);
193
    // Should use status to generate protobuf message, because it will encoding Backend Info
194
    // into the error message and then we could know which backend's pool is full.
195
3
    Status st = Status::Error<TStatusCode::CANCELLED>(
196
3
            "fail to offer request to the work pool, pool={}", pool.get_info());
197
3
    st.to_protobuf(response->mutable_status());
198
3
    LOG(WARNING) << "cancelled due to fail to offer request to the work pool, pool="
199
3
                 << pool.get_info();
200
3
}
_ZN5doris12offer_failedITkNS_9CanCancelENS_23PTabletWriterOpenResultEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Line
Count
Source
191
1
void offer_failed(T* response, google::protobuf::Closure* done, const FifoThreadPool& pool) {
192
1
    brpc::ClosureGuard closure_guard(done);
193
    // Should use status to generate protobuf message, because it will encoding Backend Info
194
    // into the error message and then we could know which backend's pool is full.
195
1
    Status st = Status::Error<TStatusCode::CANCELLED>(
196
1
            "fail to offer request to the work pool, pool={}", pool.get_info());
197
1
    st.to_protobuf(response->mutable_status());
198
    LOG(WARNING) << "cancelled due to fail to offer request to the work pool, pool="
199
1
                 << pool.get_info();
200
1
}
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_23PExecPlanFragmentResultEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
_ZN5doris12offer_failedITkNS_9CanCancelENS_23POpenLoadStreamResponseEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Line
Count
Source
191
1
void offer_failed(T* response, google::protobuf::Closure* done, const FifoThreadPool& pool) {
192
1
    brpc::ClosureGuard closure_guard(done);
193
    // Should use status to generate protobuf message, because it will encoding Backend Info
194
    // into the error message and then we could know which backend's pool is full.
195
1
    Status st = Status::Error<TStatusCode::CANCELLED>(
196
1
            "fail to offer request to the work pool, pool={}", pool.get_info());
197
1
    st.to_protobuf(response->mutable_status());
198
    LOG(WARNING) << "cancelled due to fail to offer request to the work pool, pool="
199
1
                 << pool.get_info();
200
1
}
_ZN5doris12offer_failedITkNS_9CanCancelENS_27PTabletWriterAddBlockResultEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Line
Count
Source
191
1
void offer_failed(T* response, google::protobuf::Closure* done, const FifoThreadPool& pool) {
192
1
    brpc::ClosureGuard closure_guard(done);
193
    // Should use status to generate protobuf message, because it will encoding Backend Info
194
    // into the error message and then we could know which backend's pool is full.
195
1
    Status st = Status::Error<TStatusCode::CANCELLED>(
196
1
            "fail to offer request to the work pool, pool={}", pool.get_info());
197
1
    st.to_protobuf(response->mutable_status());
198
    LOG(WARNING) << "cancelled due to fail to offer request to the work pool, pool="
199
1
                 << pool.get_info();
200
1
}
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_25PCancelPlanFragmentResultEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_21PFetchArrowDataResultEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_26POutfileWriteSuccessResultEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_23PFetchTableSchemaResultEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_29PFetchArrowFlightSchemaResultEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_24PTabletKeyLookupResponseEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_25PJdbcTestConnectionResultEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_20PFetchColIdsResponseEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_26PFetchRemoteSchemaResponseEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_12PProxyResultEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_20PMergeFilterResponseEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_23PSendFilterSizeResponseEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_23PSyncFilterSizeResponseEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_22PPublishFilterResponseEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_15PSendDataResultEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_13PCommitResultEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_15PRollbackResultEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_19PConstantExprResultEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_26PTransmitRecCTEBlockResultEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_20PRerunFragmentResultEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_20PResetGlobalRfResultEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_19PTransmitDataResultEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_24PCheckRPCChannelResponseEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_24PResetRPCChannelResponseEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_13PGlobResponseEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_26PGroupCommitInsertResponseEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_24PGetWalQueueSizeResponseEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_22PGetBeResourceResponseEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
Unexecuted instantiation: _ZN5doris12offer_failedITkNS_9CanCancelENS_23PRequestCdcClientResultEEEvPT_PN6google8protobuf7ClosureERKNS_14WorkThreadPoolILb0EEE
201
202
template <typename T>
203
class NewHttpClosure : public ::google::protobuf::Closure {
204
public:
205
    NewHttpClosure(google::protobuf::Closure* done) : _done(done) {}
206
0
    NewHttpClosure(T* request, google::protobuf::Closure* done) : _request(request), _done(done) {}
Unexecuted instantiation: _ZN5doris14NewHttpClosureINS_28PTabletWriterAddBlockRequestEEC2EPS1_PN6google8protobuf7ClosureE
Unexecuted instantiation: _ZN5doris14NewHttpClosureINS_19PTransmitDataParamsEEC2EPS1_PN6google8protobuf7ClosureE
207
208
0
    void Run() override {
209
0
        if (_request != nullptr) {
210
0
            delete _request;
211
0
            _request = nullptr;
212
0
        }
213
0
        if (_done != nullptr) {
214
0
            _done->Run();
215
0
        }
216
0
        delete this;
217
0
    }
Unexecuted instantiation: _ZN5doris14NewHttpClosureINS_28PTabletWriterAddBlockRequestEE3RunEv
Unexecuted instantiation: _ZN5doris14NewHttpClosureINS_19PTransmitDataParamsEE3RunEv
218
219
private:
220
    T* _request = nullptr;
221
    google::protobuf::Closure* _done = nullptr;
222
};
223
224
PInternalService::PInternalService(ExecEnv* exec_env)
225
21
        : _exec_env(exec_env),
226
          // heavy threadpool is used for load process and other process that will read disk or access network.
227
21
          _heavy_work_pool(config::brpc_heavy_work_pool_threads != -1
228
21
                                   ? config::brpc_heavy_work_pool_threads
229
21
                                   : std::max(128, CpuInfo::num_cores() * 4),
230
21
                           config::brpc_heavy_work_pool_max_queue_size != -1
231
21
                                   ? config::brpc_heavy_work_pool_max_queue_size
232
21
                                   : std::max(10240, CpuInfo::num_cores() * 320),
233
21
                           "brpc_heavy"),
234
          // Keep cancellation dispatch independent of potentially blocking opens and writes.
235
21
          _load_light_work_pool(config::brpc_load_light_work_pool_threads,
236
21
                                resolved_brpc_load_light_work_pool_max_queue_size(),
237
21
                                "brpc_load_light"),
238
          // peer fetch threadpool isolates fetch_peer_data from heavy load traffic to avoid peer reads starving imports.
239
21
          _peer_fetch_pool(resolved_brpc_peer_fetch_pool_threads(),
240
21
                           resolved_brpc_peer_fetch_pool_max_queue_size(), "brpc_peer_fetch"),
241
242
          // light threadpool should be only used in query processing logic. All hanlers should be very light, not locked, not access disk.
243
21
          _light_work_pool(config::brpc_light_work_pool_threads != -1
244
21
                                   ? config::brpc_light_work_pool_threads
245
21
                                   : std::max(128, CpuInfo::num_cores() * 4),
246
21
                           config::brpc_light_work_pool_max_queue_size != -1
247
21
                                   ? config::brpc_light_work_pool_max_queue_size
248
21
                                   : std::max(10240, CpuInfo::num_cores() * 320),
249
21
                           "brpc_light"),
250
21
          _arrow_flight_work_pool(config::brpc_arrow_flight_work_pool_threads != -1
251
21
                                          ? config::brpc_arrow_flight_work_pool_threads
252
21
                                          : std::max(512, CpuInfo::num_cores() * 2),
253
21
                                  config::brpc_arrow_flight_work_pool_max_queue_size != -1
254
21
                                          ? config::brpc_arrow_flight_work_pool_max_queue_size
255
21
                                          : std::max(20480, CpuInfo::num_cores() * 640),
256
21
                                  "brpc_arrow_flight") {
257
21
    REGISTER_HOOK_METRIC(load_light_work_pool_queue_size,
258
21
                         [this]() { return _load_light_work_pool.get_queue_size(); });
259
21
    REGISTER_HOOK_METRIC(load_light_work_active_threads,
260
21
                         [this]() { return _load_light_work_pool.get_active_threads(); });
261
21
    REGISTER_HOOK_METRIC(load_light_work_pool_max_queue_size,
262
21
                         []() { return resolved_brpc_load_light_work_pool_max_queue_size(); });
263
21
    REGISTER_HOOK_METRIC(load_light_work_max_threads,
264
21
                         []() { return config::brpc_load_light_work_pool_threads; });
265
266
21
    REGISTER_HOOK_METRIC(heavy_work_pool_queue_size,
267
21
                         [this]() { return _heavy_work_pool.get_queue_size(); });
268
21
    REGISTER_HOOK_METRIC(peer_fetch_work_pool_queue_size,
269
21
                         [this]() { return _peer_fetch_pool.get_queue_size(); });
270
21
    REGISTER_HOOK_METRIC(light_work_pool_queue_size,
271
21
                         [this]() { return _light_work_pool.get_queue_size(); });
272
21
    REGISTER_HOOK_METRIC(heavy_work_active_threads,
273
21
                         [this]() { return _heavy_work_pool.get_active_threads(); });
274
21
    REGISTER_HOOK_METRIC(peer_fetch_work_active_threads,
275
21
                         [this]() { return _peer_fetch_pool.get_active_threads(); });
276
21
    REGISTER_HOOK_METRIC(light_work_active_threads,
277
21
                         [this]() { return _light_work_pool.get_active_threads(); });
278
279
21
    REGISTER_HOOK_METRIC(heavy_work_pool_max_queue_size,
280
21
                         []() { return config::brpc_heavy_work_pool_max_queue_size; });
281
21
    REGISTER_HOOK_METRIC(peer_fetch_work_pool_max_queue_size,
282
21
                         []() { return resolved_brpc_peer_fetch_pool_max_queue_size(); });
283
21
    REGISTER_HOOK_METRIC(light_work_pool_max_queue_size,
284
21
                         []() { return config::brpc_light_work_pool_max_queue_size; });
285
21
    REGISTER_HOOK_METRIC(heavy_work_max_threads,
286
21
                         []() { return config::brpc_heavy_work_pool_threads; });
287
21
    REGISTER_HOOK_METRIC(peer_fetch_work_max_threads,
288
21
                         []() { return resolved_brpc_peer_fetch_pool_threads(); });
289
21
    REGISTER_HOOK_METRIC(light_work_max_threads,
290
21
                         []() { return config::brpc_light_work_pool_threads; });
291
292
21
    REGISTER_HOOK_METRIC(arrow_flight_work_pool_queue_size,
293
21
                         [this]() { return _arrow_flight_work_pool.get_queue_size(); });
294
21
    REGISTER_HOOK_METRIC(arrow_flight_work_active_threads,
295
21
                         [this]() { return _arrow_flight_work_pool.get_active_threads(); });
296
21
    REGISTER_HOOK_METRIC(arrow_flight_work_pool_max_queue_size,
297
21
                         []() { return config::brpc_arrow_flight_work_pool_max_queue_size; });
298
21
    REGISTER_HOOK_METRIC(arrow_flight_work_max_threads,
299
21
                         []() { return config::brpc_arrow_flight_work_pool_threads; });
300
301
21
    _exec_env->load_stream_mgr()->set_heavy_work_pool(&_heavy_work_pool);
302
303
21
    CHECK_EQ(0, bthread_key_create(&AsyncIO::btls_io_ctx_key, AsyncIO::io_ctx_key_deleter));
304
21
}
305
306
PInternalServiceImpl::PInternalServiceImpl(StorageEngine& engine, ExecEnv* exec_env)
307
6
        : PInternalService(exec_env), _engine(engine) {}
308
309
3
PInternalServiceImpl::~PInternalServiceImpl() = default;
310
311
17
PInternalService::~PInternalService() {
312
17
    DEREGISTER_HOOK_METRIC(load_light_work_pool_queue_size);
313
17
    DEREGISTER_HOOK_METRIC(load_light_work_active_threads);
314
17
    DEREGISTER_HOOK_METRIC(load_light_work_pool_max_queue_size);
315
17
    DEREGISTER_HOOK_METRIC(load_light_work_max_threads);
316
317
17
    DEREGISTER_HOOK_METRIC(heavy_work_pool_queue_size);
318
17
    DEREGISTER_HOOK_METRIC(peer_fetch_work_pool_queue_size);
319
17
    DEREGISTER_HOOK_METRIC(light_work_pool_queue_size);
320
17
    DEREGISTER_HOOK_METRIC(heavy_work_active_threads);
321
17
    DEREGISTER_HOOK_METRIC(peer_fetch_work_active_threads);
322
17
    DEREGISTER_HOOK_METRIC(light_work_active_threads);
323
324
17
    DEREGISTER_HOOK_METRIC(heavy_work_pool_max_queue_size);
325
17
    DEREGISTER_HOOK_METRIC(peer_fetch_work_pool_max_queue_size);
326
17
    DEREGISTER_HOOK_METRIC(light_work_pool_max_queue_size);
327
17
    DEREGISTER_HOOK_METRIC(heavy_work_max_threads);
328
17
    DEREGISTER_HOOK_METRIC(peer_fetch_work_max_threads);
329
17
    DEREGISTER_HOOK_METRIC(light_work_max_threads);
330
331
17
    DEREGISTER_HOOK_METRIC(arrow_flight_work_pool_queue_size);
332
17
    DEREGISTER_HOOK_METRIC(arrow_flight_work_active_threads);
333
17
    DEREGISTER_HOOK_METRIC(arrow_flight_work_pool_max_queue_size);
334
17
    DEREGISTER_HOOK_METRIC(arrow_flight_work_max_threads);
335
336
17
    CHECK_EQ(0, bthread_key_delete(AsyncIO::btls_io_ctx_key));
337
17
}
338
339
void PInternalService::tablet_writer_open(google::protobuf::RpcController* controller,
340
                                          const PTabletWriterOpenRequest* request,
341
                                          PTabletWriterOpenResult* response,
342
52.0k
                                          google::protobuf::Closure* done) {
343
52.2k
    bool ret = _heavy_work_pool.try_offer([this, request, response, done]() {
344
52.2k
        VLOG_RPC << "tablet writer open, id=" << request->id()
345
0
                 << ", index_id=" << request->index_id() << ", txn_id=" << request->txn_id();
346
52.2k
        signal::SignalTaskIdKeeper keeper(request->id());
347
52.2k
        brpc::ClosureGuard closure_guard(done);
348
52.2k
        auto st = _exec_env->load_channel_mgr()->open(*request);
349
52.2k
        if (!st.ok()) {
350
0
            LOG(WARNING) << "load channel open failed, message=" << st << ", id=" << request->id()
351
0
                         << ", index_id=" << request->index_id()
352
0
                         << ", txn_id=" << request->txn_id();
353
0
        }
354
52.2k
        st.to_protobuf(response->mutable_status());
355
52.2k
    });
356
52.0k
    if (!ret) {
357
1
        offer_failed(response, done, _heavy_work_pool);
358
1
        return;
359
1
    }
360
52.0k
}
361
362
void PInternalService::exec_plan_fragment(google::protobuf::RpcController* controller,
363
                                          const PExecPlanFragmentRequest* request,
364
                                          PExecPlanFragmentResult* response,
365
143k
                                          google::protobuf::Closure* done) {
366
143k
    timeval tv {};
367
143k
    gettimeofday(&tv, nullptr);
368
143k
    response->set_received_time(tv.tv_sec * 1000LL + tv.tv_usec / 1000);
369
144k
    bool ret = _light_work_pool.try_offer([this, controller, request, response, done]() {
370
144k
        _exec_plan_fragment_in_pthread(controller, request, response, done);
371
144k
    });
372
143k
    if (!ret) {
373
0
        offer_failed(response, done, _light_work_pool);
374
0
        return;
375
0
    }
376
143k
}
377
378
void PInternalService::_exec_plan_fragment_in_pthread(google::protobuf::RpcController* controller,
379
                                                      const PExecPlanFragmentRequest* request,
380
                                                      PExecPlanFragmentResult* response,
381
242k
                                                      google::protobuf::Closure* done) {
382
242k
    timeval tv1 {};
383
242k
    gettimeofday(&tv1, nullptr);
384
242k
    response->set_execution_time(tv1.tv_sec * 1000LL + tv1.tv_usec / 1000);
385
242k
    brpc::ClosureGuard closure_guard(done);
386
242k
    auto st = Status::OK();
387
18.4E
    bool compact = request->has_compact() ? request->compact() : false;
388
242k
    PFragmentRequestVersion version =
389
18.4E
            request->has_version() ? request->version() : PFragmentRequestVersion::VERSION_1;
390
242k
    try {
391
242k
        st = _exec_plan_fragment_impl(request->request(), version, compact);
392
242k
    } catch (const Exception& e) {
393
0
        st = e.to_status();
394
0
    } catch (const std::exception& e) {
395
0
        st = Status::Error(ErrorCode::INTERNAL_ERROR, e.what());
396
0
    } catch (...) {
397
0
        st = Status::Error(ErrorCode::INTERNAL_ERROR,
398
0
                           "_exec_plan_fragment_impl meet unknown error");
399
0
    }
400
242k
    if (!st.ok()) {
401
1.71k
        LOG(WARNING) << "exec plan fragment failed, errmsg=" << st;
402
1.71k
    }
403
242k
    st.to_protobuf(response->mutable_status());
404
242k
    timeval tv2 {};
405
242k
    gettimeofday(&tv2, nullptr);
406
242k
    response->set_execution_done_time(tv2.tv_sec * 1000LL + tv2.tv_usec / 1000);
407
242k
}
408
409
void PInternalService::exec_plan_fragment_prepare(google::protobuf::RpcController* controller,
410
                                                  const PExecPlanFragmentRequest* request,
411
                                                  PExecPlanFragmentResult* response,
412
98.0k
                                                  google::protobuf::Closure* done) {
413
98.0k
    timeval tv {};
414
98.0k
    gettimeofday(&tv, nullptr);
415
98.0k
    response->set_received_time(tv.tv_sec * 1000LL + tv.tv_usec / 1000);
416
98.3k
    bool ret = _light_work_pool.try_offer([this, controller, request, response, done]() {
417
98.3k
        _exec_plan_fragment_in_pthread(controller, request, response, done);
418
98.3k
    });
419
98.0k
    if (!ret) {
420
0
        offer_failed(response, done, _light_work_pool);
421
0
        return;
422
0
    }
423
98.0k
}
424
425
void PInternalService::exec_plan_fragment_start(google::protobuf::RpcController* /*controller*/,
426
                                                const PExecPlanFragmentStartRequest* request,
427
                                                PExecPlanFragmentResult* result,
428
98.2k
                                                google::protobuf::Closure* done) {
429
98.2k
    timeval tv {};
430
98.2k
    gettimeofday(&tv, nullptr);
431
98.2k
    result->set_received_time(tv.tv_sec * 1000LL + tv.tv_usec / 1000);
432
98.2k
    bool ret = _light_work_pool.try_offer([this, request, result, done]() {
433
98.2k
        timeval tv1 {};
434
98.2k
        gettimeofday(&tv1, nullptr);
435
98.2k
        result->set_execution_time(tv1.tv_sec * 1000LL + tv1.tv_usec / 1000);
436
98.2k
        brpc::ClosureGuard closure_guard(done);
437
98.2k
        auto st = _exec_env->fragment_mgr()->start_query_execution(request);
438
98.2k
        st.to_protobuf(result->mutable_status());
439
98.2k
        timeval tv2 {};
440
98.2k
        gettimeofday(&tv2, nullptr);
441
98.2k
        result->set_execution_done_time(tv2.tv_sec * 1000LL + tv2.tv_usec / 1000);
442
98.2k
    });
443
98.2k
    if (!ret) {
444
0
        offer_failed(result, done, _light_work_pool);
445
0
        return;
446
0
    }
447
98.2k
}
448
449
void PInternalService::open_load_stream(google::protobuf::RpcController* controller,
450
                                        const POpenLoadStreamRequest* request,
451
                                        POpenLoadStreamResponse* response,
452
26
                                        google::protobuf::Closure* done) {
453
26
    bool ret = _heavy_work_pool.try_offer([this, controller, request, response, done]() {
454
24
        signal::SignalTaskIdKeeper keeper(request->load_id());
455
24
        brpc::ClosureGuard done_guard(done);
456
24
        brpc::Controller* cntl = static_cast<brpc::Controller*>(controller);
457
24
        brpc::StreamOptions stream_options;
458
459
24
        LOG(INFO) << "open load stream, load_id=" << request->load_id()
460
24
                  << ", src_id=" << request->src_id();
461
462
24
        std::vector<BaseTabletSPtr> tablets;
463
24
        for (const auto& req : request->tablets()) {
464
12
            BaseTabletSPtr tablet;
465
12
            if (auto res = ExecEnv::get_tablet(req.tablet_id()); !res.has_value()) [[unlikely]] {
466
0
                auto st = std::move(res).error();
467
0
                st.to_protobuf(response->mutable_status());
468
0
                cntl->SetFailed(st.to_string());
469
0
                return;
470
12
            } else {
471
12
                tablet = std::move(res).value();
472
12
            }
473
12
            auto resp = response->add_tablet_schemas();
474
12
            resp->set_index_id(req.index_id());
475
12
            resp->set_enable_unique_key_merge_on_write(tablet->enable_unique_key_merge_on_write());
476
12
            tablet->tablet_schema()->to_schema_pb(resp->mutable_tablet_schema());
477
12
            tablets.push_back(tablet);
478
12
        }
479
24
        if (!tablets.empty()) {
480
12
            auto* tablet_load_infos = response->mutable_tablet_load_rowset_num_infos();
481
12
            for (const auto& tablet : tablets) {
482
12
                BaseDeltaWriter::collect_tablet_load_rowset_num_info(tablet.get(),
483
12
                                                                     tablet_load_infos);
484
12
            }
485
12
        }
486
487
24
        LoadStream* load_stream = nullptr;
488
24
        auto st = _exec_env->load_stream_mgr()->open_load_stream(request, load_stream);
489
24
        if (!st.ok()) {
490
0
            st.to_protobuf(response->mutable_status());
491
0
            return;
492
0
        }
493
494
24
        stream_options.handler = load_stream;
495
24
        stream_options.idle_timeout_ms = request->idle_timeout_ms();
496
24
        DBUG_EXECUTE_IF("PInternalServiceImpl.open_load_stream.set_idle_timeout",
497
24
                        { stream_options.idle_timeout_ms = 1; });
498
499
24
        StreamId streamid;
500
24
        if (brpc::StreamAccept(&streamid, *cntl, &stream_options) != 0) {
501
0
            st = Status::Cancelled("Fail to accept stream {}", streamid);
502
0
            st.to_protobuf(response->mutable_status());
503
0
            cntl->SetFailed(st.to_string());
504
0
            return;
505
0
        }
506
507
24
        VLOG_DEBUG << "get streamid =" << streamid;
508
24
        st.to_protobuf(response->mutable_status());
509
24
    });
510
26
    if (!ret) {
511
1
        offer_failed(response, done, _heavy_work_pool);
512
1
    }
513
26
}
514
515
void PInternalService::tablet_writer_add_block_by_http(google::protobuf::RpcController* controller,
516
                                                       const ::doris::PEmptyRequest* request,
517
                                                       PTabletWriterAddBlockResult* response,
518
0
                                                       google::protobuf::Closure* done) {
519
0
    PTabletWriterAddBlockRequest* new_request = new PTabletWriterAddBlockRequest();
520
0
    google::protobuf::Closure* new_done =
521
0
            new NewHttpClosure<PTabletWriterAddBlockRequest>(new_request, done);
522
0
    brpc::Controller* cntl = static_cast<brpc::Controller*>(controller);
523
0
    Status st = attachment_extract_request_contain_block<PTabletWriterAddBlockRequest>(new_request,
524
0
                                                                                       cntl);
525
0
    if (st.ok()) {
526
0
        tablet_writer_add_block(controller, new_request, response, new_done);
527
0
    } else {
528
0
        st.to_protobuf(response->mutable_status());
529
0
    }
530
0
}
531
532
void PInternalService::tablet_writer_add_block(google::protobuf::RpcController* controller,
533
                                               const PTabletWriterAddBlockRequest* request,
534
                                               PTabletWriterAddBlockResult* response,
535
58.0k
                                               google::protobuf::Closure* done) {
536
58.0k
    int64_t submit_task_time_ns = MonotonicNanos();
537
58.4k
    bool ret = _heavy_work_pool.try_offer([request, response, done, submit_task_time_ns, this]() {
538
58.4k
        int64_t wait_execution_time_ns = MonotonicNanos() - submit_task_time_ns;
539
58.4k
        brpc::ClosureGuard closure_guard(done);
540
58.4k
        int64_t execution_time_ns = 0;
541
58.4k
        std::shared_ptr<EosCompletion> eos_completion;
542
58.4k
        {
543
58.4k
            SCOPED_RAW_TIMER(&execution_time_ns);
544
58.4k
            signal::SignalTaskIdKeeper keeper(request->id());
545
58.4k
            auto st = _exec_env->load_channel_mgr()->add_batch(*request, response, &eos_completion);
546
58.4k
            if (!st.ok()) {
547
48
                LOG(WARNING) << "tablet writer add block failed, message=" << st
548
48
                             << ", id=" << request->id() << ", index_id=" << request->index_id()
549
48
                             << ", sender_id=" << request->sender_id()
550
48
                             << ", backend id=" << request->backend_id();
551
48
            }
552
58.4k
            st.to_protobuf(response->mutable_status());
553
58.4k
        }
554
58.4k
        response->set_execution_time_us(execution_time_ns / NANOS_PER_MICRO);
555
58.4k
        response->set_wait_execution_time_us(wait_execution_time_ns / NANOS_PER_MICRO);
556
58.4k
        if (eos_completion && response->status().status_code() == TStatusCode::OK) {
557
            // Transfer done before publishing the callback: a completed barrier
558
            // can invoke it inline. All request/response access above must end
559
            // first, including profiling, timers and SignalTaskIdKeeper.
560
0
            auto* deferred_done = closure_guard.release();
561
0
            eos_completion->add_waiter([response, deferred_done](const Status& status) {
562
0
                status.to_protobuf(response->mutable_status());
563
0
                deferred_done->Run();
564
                // The RPC objects (including HTTP's request wrapper) are gone.
565
0
            });
566
0
        }
567
58.4k
    });
568
58.0k
    if (!ret) {
569
1
        offer_failed(response, done, _heavy_work_pool);
570
1
        return;
571
1
    }
572
58.0k
}
573
574
void PInternalService::tablet_writer_cancel(google::protobuf::RpcController* controller,
575
                                            const PTabletWriterCancelRequest* request,
576
                                            PTabletWriterCancelResult* response,
577
192
                                            google::protobuf::Closure* done) {
578
192
    bool ret = _load_light_work_pool.try_offer([this, request, done]() {
579
191
        VLOG_RPC << "tablet writer cancel, id=" << request->id()
580
0
                 << ", index_id=" << request->index_id() << ", sender_id=" << request->sender_id();
581
191
        signal::SignalTaskIdKeeper keeper(request->id());
582
191
        brpc::ClosureGuard closure_guard(done);
583
191
        auto st = _exec_env->load_channel_mgr()->cancel(*request);
584
191
        if (!st.ok()) {
585
0
            LOG(WARNING) << "tablet writer cancel failed, id=" << request->id()
586
0
                         << ", index_id=" << request->index_id()
587
0
                         << ", sender_id=" << request->sender_id();
588
0
        }
589
191
    });
590
192
    if (!ret) {
591
1
        offer_failed(response, done, _load_light_work_pool);
592
1
        return;
593
1
    }
594
192
}
595
596
Status PInternalService::_exec_plan_fragment_impl(
597
        const std::string& ser_request, PFragmentRequestVersion version, bool compact,
598
242k
        const std::function<void(RuntimeState*, Status*)>& cb) {
599
    // Sometimes the BE do not receive the first heartbeat message and it receives request from FE
600
    // If BE execute this fragment, it will core when it wants to get some property from master info.
601
242k
    if (ExecEnv::GetInstance()->cluster_info() == nullptr) {
602
0
        return Status::InternalError(
603
0
                "Have not receive the first heartbeat message from master, not ready to provide "
604
0
                "service");
605
0
    }
606
242k
    CHECK(version == PFragmentRequestVersion::VERSION_3)
607
0
            << "only support version 3, received " << version;
608
242k
    if (version == PFragmentRequestVersion::VERSION_3) {
609
242k
        TPipelineFragmentParamsList t_request;
610
242k
        {
611
242k
            const uint8_t* buf = (const uint8_t*)ser_request.data();
612
242k
            uint32_t len = ser_request.size();
613
242k
            RETURN_IF_ERROR(deserialize_thrift_msg(buf, &len, compact, &t_request));
614
242k
        }
615
616
242k
        const auto& fragment_list = t_request.params_list;
617
242k
        if (fragment_list.empty()) {
618
0
            return Status::InternalError("Invalid TPipelineFragmentParamsList!");
619
0
        }
620
242k
        MonotonicStopWatch timer;
621
242k
        timer.start();
622
623
        // work for old version frontend
624
242k
        if (!t_request.__isset.runtime_filter_info) {
625
74.3k
            TRuntimeFilterInfo runtime_filter_info;
626
74.3k
            auto local_param = fragment_list[0].local_params[0];
627
74.3k
            if (local_param.__isset.runtime_filter_params) {
628
74.3k
                runtime_filter_info.__set_runtime_filter_params(local_param.runtime_filter_params);
629
74.3k
            }
630
74.3k
            if (local_param.__isset.topn_filter_descs) {
631
0
                runtime_filter_info.__set_topn_filter_descs(local_param.topn_filter_descs);
632
0
            }
633
74.3k
            t_request.__set_runtime_filter_info(runtime_filter_info);
634
74.3k
        }
635
636
360k
        for (const TPipelineFragmentParams& fragment : fragment_list) {
637
360k
            if (cb) {
638
29
                RETURN_IF_ERROR(_exec_env->fragment_mgr()->exec_plan_fragment(
639
29
                        fragment, QuerySource::INTERNAL_FRONTEND, cb, t_request));
640
360k
            } else {
641
360k
                RETURN_IF_ERROR(_exec_env->fragment_mgr()->exec_plan_fragment(
642
360k
                        fragment, QuerySource::INTERNAL_FRONTEND, t_request));
643
360k
            }
644
360k
        }
645
240k
        timer.stop();
646
240k
        double cost_secs = static_cast<double>(timer.elapsed_time()) / 1000000000ULL;
647
240k
        if (cost_secs > 5) {
648
16
            LOG_WARNING("Prepare {} fragments of query {} costs {} seconds, it costs too much",
649
16
                        fragment_list.size(), print_id(fragment_list.front().query_id), cost_secs);
650
16
        }
651
652
240k
        return Status::OK();
653
242k
    } else {
654
0
        return Status::InternalError("invalid version");
655
0
    }
656
242k
}
657
658
void PInternalService::cancel_plan_fragment(google::protobuf::RpcController* /*controller*/,
659
                                            const PCancelPlanFragmentRequest* request,
660
                                            PCancelPlanFragmentResult* result,
661
167k
                                            google::protobuf::Closure* done) {
662
168k
    bool ret = _light_work_pool.try_offer([this, request, result, done]() {
663
168k
        brpc::ClosureGuard closure_guard(done);
664
168k
        signal::SignalTaskIdKeeper keeper(request->finst_id());
665
168k
        Status st = Status::OK();
666
667
168k
        const bool has_cancel_reason = request->has_cancel_reason();
668
168k
        const bool has_cancel_status = request->has_cancel_status();
669
        // During upgrade only LIMIT_REACH is used, other reason is changed to internal error
670
168k
        Status actual_cancel_status = Status::OK();
671
        // Convert PPlanFragmentCancelReason to Status
672
168k
        if (has_cancel_status) {
673
            // If fe set cancel status, then it is new FE now, should use cancel status.
674
168k
            actual_cancel_status = Status::create<false>(request->cancel_status());
675
168k
        } else if (has_cancel_reason) {
676
            // If fe not set cancel status, but set cancel reason, should convert cancel reason
677
            // to cancel status here.
678
0
            if (request->cancel_reason() == PPlanFragmentCancelReason::LIMIT_REACH) {
679
0
                actual_cancel_status = Status::Error<ErrorCode::LIMIT_REACH>("limit reach");
680
0
            } else {
681
                // Use cancel reason as error message
682
0
                actual_cancel_status = Status::InternalError(
683
0
                        PPlanFragmentCancelReason_Name(request->cancel_reason()));
684
0
            }
685
0
        } else {
686
0
            actual_cancel_status = Status::InternalError("unknown error");
687
0
        }
688
689
168k
        TUniqueId query_id;
690
168k
        query_id.__set_hi(request->query_id().hi());
691
168k
        query_id.__set_lo(request->query_id().lo());
692
168k
        LOG(INFO) << fmt::format("Cancel query {}, reason: {}", print_id(query_id),
693
168k
                                 actual_cancel_status.to_string());
694
168k
        _exec_env->fragment_mgr()->cancel_query(query_id, actual_cancel_status);
695
        // LIMIT_REACH/FINISHED can leave valid unread results; only an abort may discard them.
696
168k
        if (!actual_cancel_status.ok() && !actual_cancel_status.is<ErrorCode::LIMIT_REACH>() &&
697
168k
            !actual_cancel_status.is<ErrorCode::FINISHED>()) {
698
3.91k
            _exec_env->result_mgr()->cancel_arrow_flight_buffers(query_id, actual_cancel_status);
699
3.91k
        }
700
701
        // TODO: the logic seems useless, cancel only return Status::OK. remove it
702
168k
        st.to_protobuf(result->mutable_status());
703
168k
    });
704
167k
    if (!ret) {
705
0
        offer_failed(result, done, _light_work_pool);
706
0
        return;
707
0
    }
708
167k
}
709
710
void PInternalService::fetch_data(google::protobuf::RpcController* controller,
711
                                  const PFetchDataRequest* request, PFetchDataResult* result,
712
348k
                                  google::protobuf::Closure* done) {
713
    // fetch_data is a light operation which will put a request rather than wait inplace when there's no data ready.
714
    // when there's data ready, use brpc to send. there's queue in brpc service. won't take it too long.
715
348k
    auto ctx = GetResultBatchCtx::create_shared(result, done);
716
348k
    TUniqueId unique_id = UniqueId(request->finst_id()).to_thrift(); // query_id or instance_id
717
348k
    std::shared_ptr<MySQLResultBlockBuffer> buffer;
718
348k
    Status st = ExecEnv::GetInstance()->result_mgr()->find_buffer(unique_id, buffer);
719
348k
    if (!st.ok()) {
720
0
        LOG(WARNING) << "Result buffer not found! finst ID: " << print_id(unique_id);
721
0
        return;
722
0
    }
723
348k
    if (st = buffer->get_batch(ctx); !st.ok()) {
724
15
        LOG(WARNING) << "fetch_data failed: " << st.to_string();
725
15
    }
726
348k
}
727
728
void PInternalService::fetch_arrow_data(google::protobuf::RpcController* controller,
729
                                        const PFetchArrowDataRequest* request,
730
                                        PFetchArrowDataResult* result,
731
3
                                        google::protobuf::Closure* done) {
732
3
    bool ret = _arrow_flight_work_pool.try_offer([request, result, done]() {
733
3
        auto ctx = GetArrowResultBatchCtx::create_shared(result, done);
734
3
        TUniqueId unique_id = UniqueId(request->finst_id()).to_thrift(); // query_id or instance_id
735
3
        std::shared_ptr<ArrowFlightResultBlockBuffer> arrow_buffer;
736
3
        auto st = ExecEnv::GetInstance()->result_mgr()->find_buffer(unique_id, arrow_buffer);
737
3
        if (!st.ok()) {
738
1
            LOG(WARNING) << "Result buffer not found! Query ID: " << print_id(unique_id);
739
1
            ctx->on_failure(st);
740
1
            return;
741
1
        }
742
2
        if (st = arrow_buffer->get_batch(ctx); !st.ok()) {
743
0
            LOG(WARNING) << "fetch_arrow_data failed: " << st.to_string();
744
0
        }
745
2
    });
746
3
    if (!ret) {
747
0
        offer_failed(result, done, _arrow_flight_work_pool);
748
0
        return;
749
0
    }
750
3
}
751
752
void PInternalService::outfile_write_success(google::protobuf::RpcController* controller,
753
                                             const POutfileWriteSuccessRequest* request,
754
                                             POutfileWriteSuccessResult* result,
755
4
                                             google::protobuf::Closure* done) {
756
4
    bool ret = _heavy_work_pool.try_offer([request, result, done]() {
757
4
        VLOG_RPC << "outfile write success file";
758
4
        brpc::ClosureGuard closure_guard(done);
759
4
        TResultFileSink result_file_sink;
760
4
        Status st = Status::OK();
761
4
        {
762
4
            const uint8_t* buf = (const uint8_t*)(request->result_file_sink().data());
763
4
            uint32_t len = request->result_file_sink().size();
764
4
            st = deserialize_thrift_msg(buf, &len, false, &result_file_sink);
765
4
            if (!st.ok()) {
766
0
                LOG(WARNING) << "outfile write success file failed, errmsg = " << st;
767
0
                st.to_protobuf(result->mutable_status());
768
0
                return;
769
0
            }
770
4
        }
771
772
4
        TResultFileSinkOptions file_options = result_file_sink.file_options;
773
4
        std::stringstream ss;
774
4
        ss << file_options.file_path << file_options.success_file_name;
775
4
        std::string file_name = ss.str();
776
4
        if (result_file_sink.storage_backend_type == TStorageBackendType::LOCAL) {
777
            // For local file writer, the file_path is a local dir.
778
            // Here we do a simple security verification by checking whether the file exists.
779
            // Because the file path is currently arbitrarily specified by the user,
780
            // Doris is not responsible for ensuring the correctness of the path.
781
            // This is just to prevent overwriting the existing file.
782
4
            bool exists = true;
783
4
            st = io::global_local_filesystem()->exists(file_name, &exists);
784
4
            if (!st.ok()) {
785
0
                LOG(WARNING) << "outfile write success filefailed, errmsg = " << st;
786
0
                st.to_protobuf(result->mutable_status());
787
0
                return;
788
0
            }
789
4
            if (exists) {
790
0
                st = Status::InternalError("File already exists: {}", file_name);
791
0
            }
792
4
            if (!st.ok()) {
793
0
                LOG(WARNING) << "outfile write success file failed, errmsg = " << st;
794
0
                st.to_protobuf(result->mutable_status());
795
0
                return;
796
0
            }
797
4
        }
798
799
4
        auto file_type_res =
800
4
                FileFactory::convert_storage_type(result_file_sink.storage_backend_type);
801
4
        if (!file_type_res.has_value()) [[unlikely]] {
802
0
            st = std::move(file_type_res).error();
803
0
            st.to_protobuf(result->mutable_status());
804
0
            LOG(WARNING) << "encounter unkonw type=" << result_file_sink.storage_backend_type
805
0
                         << ", st=" << st;
806
0
            return;
807
0
        }
808
809
4
        auto&& res = FileFactory::create_file_writer(file_type_res.value(), ExecEnv::GetInstance(),
810
4
                                                     file_options.broker_addresses,
811
4
                                                     file_options.broker_properties, file_name,
812
4
                                                     {
813
4
                                                             .write_file_cache = false,
814
4
                                                             .sync_file_data = false,
815
4
                                                     });
816
4
        using T = std::decay_t<decltype(res)>;
817
4
        if (!res.has_value()) [[unlikely]] {
818
0
            st = std::forward<T>(res).error();
819
0
            st.to_protobuf(result->mutable_status());
820
0
            return;
821
0
        }
822
823
4
        std::unique_ptr<doris::io::FileWriter> _file_writer_impl = std::forward<T>(res).value();
824
        // must write somthing because s3 file writer can not writer empty file
825
4
        st = _file_writer_impl->append({"success"});
826
4
        if (!st.ok()) {
827
0
            LOG(WARNING) << "outfile write success filefailed, errmsg=" << st;
828
0
            st.to_protobuf(result->mutable_status());
829
0
            return;
830
0
        }
831
4
        st = _file_writer_impl->close();
832
4
        if (!st.ok()) {
833
0
            LOG(WARNING) << "outfile write success filefailed, errmsg=" << st;
834
0
            st.to_protobuf(result->mutable_status());
835
0
            return;
836
0
        }
837
4
    });
838
4
    if (!ret) {
839
0
        offer_failed(result, done, _heavy_work_pool);
840
0
        return;
841
0
    }
842
4
}
843
844
void PInternalService::fetch_table_schema(google::protobuf::RpcController* controller,
845
                                          const PFetchTableSchemaRequest* request,
846
                                          PFetchTableSchemaResult* result,
847
732
                                          google::protobuf::Closure* done) {
848
732
    bool ret = _heavy_work_pool.try_offer([request, result, done]() {
849
732
        VLOG_RPC << "fetch table schema";
850
732
        brpc::ClosureGuard closure_guard(done);
851
732
        TFileScanRange file_scan_range;
852
732
        Status st = Status::OK();
853
732
        {
854
732
            const uint8_t* buf = (const uint8_t*)(request->file_scan_range().data());
855
732
            uint32_t len = request->file_scan_range().size();
856
732
            st = deserialize_thrift_msg(buf, &len, false, &file_scan_range);
857
732
            if (!st.ok()) {
858
0
                LOG(WARNING) << "fetch table schema failed, errmsg=" << st;
859
0
                st.to_protobuf(result->mutable_status());
860
0
                return;
861
0
            }
862
732
        }
863
732
        if (file_scan_range.__isset.ranges == false) {
864
0
            st = Status::InternalError("can not get TFileRangeDesc.");
865
0
            st.to_protobuf(result->mutable_status());
866
0
            return;
867
0
        }
868
732
        if (file_scan_range.__isset.params == false) {
869
0
            st = Status::InternalError("can not get TFileScanRangeParams.");
870
0
            st.to_protobuf(result->mutable_status());
871
0
            return;
872
0
        }
873
732
        const TFileRangeDesc& range = file_scan_range.ranges.at(0);
874
732
        const TFileScanRangeParams& params = file_scan_range.params;
875
876
732
        std::shared_ptr<MemTrackerLimiter> mem_tracker = MemTrackerLimiter::create_shared(
877
732
                MemTrackerLimiter::Type::OTHER,
878
732
                fmt::format("InternalService::fetch_table_schema:{}#{}", params.format_type,
879
732
                            params.file_type));
880
732
        SCOPED_ATTACH_TASK(mem_tracker);
881
882
        // make sure profile is desctructed after reader cause PrefetchBufferedReader
883
        // might asynchronouslly access the profile
884
732
        std::unique_ptr<RuntimeProfile> profile =
885
732
                std::make_unique<RuntimeProfile>("FetchTableSchema");
886
732
        auto io_ctx = std::make_shared<io::IOContext>();
887
732
        auto file_cache_statis = std::make_shared<io::FileCacheStatistics>();
888
732
        auto file_reader_stats = std::make_shared<io::FileReaderStats>();
889
732
        io_ctx->file_cache_stats = file_cache_statis.get();
890
732
        io_ctx->file_reader_stats = file_reader_stats.get();
891
732
        std::vector<format::ColumnDefinition> schema;
892
732
        st = format::fetch_file_schema(params, range, io_ctx, profile.get(), &schema);
893
732
        if (st.ok()) {
894
727
            result->set_column_nums(schema.size());
895
4.38k
            for (const auto& column : schema) {
896
4.38k
                result->add_column_names(column.name);
897
4.38k
                column.type->to_protobuf(result->add_column_types());
898
4.38k
            }
899
727
        }
900
732
        st.to_protobuf(result->mutable_status());
901
732
    });
902
732
    if (!ret) {
903
0
        offer_failed(result, done, _heavy_work_pool);
904
0
        return;
905
0
    }
906
732
}
907
908
void PInternalService::fetch_arrow_flight_schema(google::protobuf::RpcController* controller,
909
                                                 const PFetchArrowFlightSchemaRequest* request,
910
                                                 PFetchArrowFlightSchemaResult* result,
911
97
                                                 google::protobuf::Closure* done) {
912
97
    bool ret = _arrow_flight_work_pool.try_offer([request, result, done]() {
913
97
        brpc::ClosureGuard closure_guard(done);
914
97
        std::shared_ptr<arrow::Schema> schema;
915
97
        std::shared_ptr<ArrowFlightResultBlockBuffer> buffer;
916
97
        auto st = ExecEnv::GetInstance()->result_mgr()->find_buffer(
917
97
                UniqueId(request->finst_id()).to_thrift(), buffer);
918
97
        if (!st.ok()) {
919
0
            LOG(WARNING) << "fetch arrow flight schema failed, errmsg=" << st;
920
0
            st.to_protobuf(result->mutable_status());
921
0
            return;
922
0
        }
923
97
        st = buffer->get_schema(&schema);
924
97
        if (!st.ok()) {
925
0
            LOG(WARNING) << "fetch arrow flight schema failed, errmsg=" << st;
926
0
            st.to_protobuf(result->mutable_status());
927
0
            return;
928
0
        }
929
930
97
        std::string schema_str;
931
97
        st = serialize_arrow_schema(&schema, &schema_str);
932
97
        if (st.ok()) {
933
97
            result->set_schema(std::move(schema_str));
934
97
            if (!config::public_host.empty()) {
935
0
                result->set_be_arrow_flight_ip(config::public_host);
936
0
            }
937
97
            if (config::arrow_flight_sql_proxy_port != -1) {
938
0
                result->set_be_arrow_flight_port(config::arrow_flight_sql_proxy_port);
939
0
            }
940
97
        }
941
97
        st.to_protobuf(result->mutable_status());
942
97
    });
943
97
    if (!ret) {
944
0
        offer_failed(result, done, _arrow_flight_work_pool);
945
0
        return;
946
0
    }
947
97
}
948
949
Status PInternalService::_tablet_fetch_data(const PTabletKeyLookupRequest* request,
950
273
                                            PTabletKeyLookupResponse* response) {
951
273
    PointQueryExecutor executor;
952
273
    RETURN_IF_ERROR_OR_CATCH_EXCEPTION(executor.init(request, response));
953
273
    if (response->has_need_resend_query_context() && response->need_resend_query_context()) {
954
1
        return Status::OK();
955
1
    }
956
272
    RETURN_IF_ERROR_OR_CATCH_EXCEPTION(executor.lookup_up());
957
269
    executor.print_profile();
958
269
    return Status::OK();
959
272
}
960
961
void PInternalService::tablet_fetch_data(google::protobuf::RpcController* controller,
962
                                         const PTabletKeyLookupRequest* request,
963
                                         PTabletKeyLookupResponse* response,
964
273
                                         google::protobuf::Closure* done) {
965
273
    bool ret = _light_work_pool.try_offer([this, controller, request, response, done]() {
966
273
        [[maybe_unused]] auto* cntl = static_cast<brpc::Controller*>(controller);
967
273
        brpc::ClosureGuard guard(done);
968
273
        Status st = _tablet_fetch_data(request, response);
969
273
        st.to_protobuf(response->mutable_status());
970
273
    });
971
273
    if (!ret) {
972
0
        offer_failed(response, done, _light_work_pool);
973
0
        return;
974
0
    }
975
273
}
976
977
void PInternalService::test_jdbc_connection(google::protobuf::RpcController* controller,
978
                                            const PJdbcTestConnectionRequest* request,
979
                                            PJdbcTestConnectionResult* result,
980
3
                                            google::protobuf::Closure* done) {
981
3
    if (!doris::config::enable_java_support) {
982
0
        doris::Status status = doris::Status::InternalError(
983
0
                "you can change be config enable_java_support to true and restart be.");
984
0
        status.to_protobuf(result->mutable_status());
985
0
        done->Run();
986
0
        return;
987
0
    }
988
3
    bool ret = _heavy_work_pool.try_offer([request, result, done]() {
989
3
        VLOG_RPC << "test jdbc connection";
990
3
        brpc::ClosureGuard closure_guard(done);
991
3
        std::shared_ptr<MemTrackerLimiter> mem_tracker = MemTrackerLimiter::create_shared(
992
3
                MemTrackerLimiter::Type::OTHER,
993
3
                fmt::format("InternalService::test_jdbc_connection"));
994
3
        SCOPED_ATTACH_TASK(mem_tracker);
995
3
        TTableDescriptor table_desc;
996
3
        Status st = Status::OK();
997
3
        {
998
3
            const uint8_t* buf = (const uint8_t*)request->jdbc_table().data();
999
3
            uint32_t len = request->jdbc_table().size();
1000
3
            st = deserialize_thrift_msg(buf, &len, false, &table_desc);
1001
3
            if (!st.ok()) {
1002
0
                LOG(WARNING) << "test jdbc connection failed, errmsg=" << st;
1003
0
                st.to_protobuf(result->mutable_status());
1004
0
                return;
1005
0
            }
1006
3
        }
1007
3
        TJdbcTable jdbc_table = (table_desc.jdbcTable);
1008
1009
        // Resolve driver URL to absolute file:// path
1010
3
        std::string driver_url;
1011
3
        st = JdbcUtils::resolve_driver_url(jdbc_table.jdbc_driver_url, &driver_url);
1012
3
        if (!st.ok()) {
1013
0
            st.to_protobuf(result->mutable_status());
1014
0
            return;
1015
0
        }
1016
1017
        // Build params for JdbcConnectionTester
1018
3
        std::map<std::string, std::string> params;
1019
3
        params["jdbc_url"] = jdbc_table.jdbc_url;
1020
3
        params["jdbc_user"] = jdbc_table.jdbc_user;
1021
3
        params["jdbc_password"] = jdbc_table.jdbc_password;
1022
3
        params["jdbc_driver_class"] = jdbc_table.jdbc_driver_class;
1023
3
        params["jdbc_driver_url"] = driver_url;
1024
        // The catalog's expected MD5. Without it JdbcConnectionTester reads "" and
1025
        // JdbcDriverUtils.checksumVerifier("") is a no-op, so the one request whose entire job is
1026
        // to validate a catalog definition accepted any jar at all behind the driver URL.
1027
3
        params["jdbc_driver_checksum"] = jdbc_table.jdbc_driver_checksum;
1028
3
        params["query_sql"] = request->query_str();
1029
3
        params["catalog_id"] = std::to_string(jdbc_table.catalog_id);
1030
3
        params["connection_pool_min_size"] = std::to_string(jdbc_table.connection_pool_min_size);
1031
3
        params["connection_pool_max_size"] = std::to_string(jdbc_table.connection_pool_max_size);
1032
3
        params["connection_pool_max_wait_time"] =
1033
3
                std::to_string(jdbc_table.connection_pool_max_wait_time);
1034
3
        params["connection_pool_max_life_time"] =
1035
3
                std::to_string(jdbc_table.connection_pool_max_life_time);
1036
3
        params["connection_pool_keep_alive"] =
1037
3
                jdbc_table.connection_pool_keep_alive ? "true" : "false";
1038
3
        params["clean_datasource"] = "true";
1039
        // Map jdbc_table_type (TOdbcTableType enum value) to string name
1040
        // for JdbcTypeHandlerFactory to select the correct type handler.
1041
        // This ensures the right validation query is used (e.g. Oracle: "SELECT 1 FROM dual").
1042
3
        if (request->has_jdbc_table_type()) {
1043
3
            std::string type_name;
1044
3
            switch (request->jdbc_table_type()) {
1045
3
            case 0:
1046
3
                type_name = "MYSQL";
1047
3
                break;
1048
0
            case 1:
1049
0
                type_name = "ORACLE";
1050
0
                break;
1051
0
            case 2:
1052
0
                type_name = "POSTGRESQL";
1053
0
                break;
1054
0
            case 3:
1055
0
                type_name = "SQLSERVER";
1056
0
                break;
1057
0
            case 6:
1058
0
                type_name = "CLICKHOUSE";
1059
0
                break;
1060
0
            case 7:
1061
0
                type_name = "SAP_HANA";
1062
0
                break;
1063
0
            case 8:
1064
0
                type_name = "TRINO";
1065
0
                break;
1066
0
            case 9:
1067
0
                type_name = "PRESTO";
1068
0
                break;
1069
0
            case 10:
1070
0
                type_name = "OCEANBASE";
1071
0
                break;
1072
0
            case 11:
1073
0
                type_name = "OCEANBASE_ORACLE";
1074
0
                break;
1075
0
            case 13:
1076
0
                type_name = "DB2";
1077
0
                break;
1078
0
            case 14:
1079
0
                type_name = "GBASE";
1080
0
                break;
1081
0
            default:
1082
0
                break;
1083
3
            }
1084
3
            if (!type_name.empty()) {
1085
3
                params["table_type"] = type_name;
1086
3
            }
1087
3
        }
1088
        // required_fields and columns_types are required by JniReader
1089
3
        params["required_fields"] = "result";
1090
3
        params["columns_types"] = "int";
1091
1092
        // Use JniReader to create JdbcConnectionTester, which tests
1093
        // the connection in its open() method.
1094
3
        auto jni_reader = std::make_unique<JniReader>(Jni::plugin::JDBC_CONNECTION_TESTER, params);
1095
3
        st = jni_reader->open(nullptr, nullptr);
1096
3
        st.to_protobuf(result->mutable_status());
1097
1098
3
        Status close_st = jni_reader->close();
1099
3
        if (!close_st.ok()) {
1100
0
            LOG(WARNING) << "Failed to close JDBC connection tester: " << close_st.msg();
1101
0
        }
1102
3
    });
1103
1104
3
    if (!ret) {
1105
0
        offer_failed(result, done, _heavy_work_pool);
1106
0
        return;
1107
0
    }
1108
3
}
1109
1110
void PInternalServiceImpl::get_column_ids_by_tablet_ids(google::protobuf::RpcController* controller,
1111
                                                        const PFetchColIdsRequest* request,
1112
                                                        PFetchColIdsResponse* response,
1113
0
                                                        google::protobuf::Closure* done) {
1114
0
    bool ret = _light_work_pool.try_offer([this, controller, request, response, done]() {
1115
0
        _get_column_ids_by_tablet_ids(controller, request, response, done);
1116
0
    });
1117
0
    if (!ret) {
1118
0
        offer_failed(response, done, _light_work_pool);
1119
0
        return;
1120
0
    }
1121
0
}
1122
1123
void PInternalServiceImpl::_get_column_ids_by_tablet_ids(
1124
        google::protobuf::RpcController* controller, const PFetchColIdsRequest* request,
1125
0
        PFetchColIdsResponse* response, google::protobuf::Closure* done) {
1126
0
    brpc::ClosureGuard guard(done);
1127
0
    [[maybe_unused]] auto* cntl = static_cast<brpc::Controller*>(controller);
1128
0
    TabletManager* tablet_mgr = _engine.tablet_manager();
1129
0
    const auto& params = request->params();
1130
0
    for (const auto& param : params) {
1131
0
        int64_t index_id = param.indexid();
1132
0
        const auto& tablet_ids = param.tablet_ids();
1133
0
        std::set<std::set<int32_t>> filter_set;
1134
0
        std::map<int32_t, const TabletColumn*> id_to_column;
1135
0
        for (const int64_t tablet_id : tablet_ids) {
1136
0
            TabletSharedPtr tablet = tablet_mgr->get_tablet(tablet_id);
1137
0
            if (tablet == nullptr) {
1138
0
                std::stringstream ss;
1139
0
                ss << "cannot get tablet by id:" << tablet_id;
1140
0
                LOG(WARNING) << ss.str();
1141
0
                response->mutable_status()->set_status_code(TStatusCode::ILLEGAL_STATE);
1142
0
                response->mutable_status()->add_error_msgs(ss.str());
1143
0
                return;
1144
0
            }
1145
            // check schema consistency, column ids should be the same
1146
0
            const auto& columns = tablet->tablet_schema()->columns();
1147
1148
0
            std::set<int32_t> column_ids;
1149
0
            for (const auto& col : columns) {
1150
0
                column_ids.insert(col->unique_id());
1151
0
            }
1152
0
            filter_set.insert(std::move(column_ids));
1153
1154
0
            if (id_to_column.empty()) {
1155
0
                for (const auto& col : columns) {
1156
0
                    id_to_column.insert(std::pair {col->unique_id(), col.get()});
1157
0
                }
1158
0
            } else {
1159
0
                for (const auto& col : columns) {
1160
0
                    auto it = id_to_column.find(col->unique_id());
1161
0
                    if (it == id_to_column.end() || *(it->second) != *col) {
1162
0
                        ColumnPB prev_col_pb;
1163
0
                        ColumnPB curr_col_pb;
1164
0
                        if (it != id_to_column.end()) {
1165
0
                            it->second->to_schema_pb(&prev_col_pb);
1166
0
                        }
1167
0
                        col->to_schema_pb(&curr_col_pb);
1168
0
                        std::stringstream ss;
1169
0
                        ss << "consistency check failed: index{ " << index_id << " }"
1170
0
                           << " got inconsistent schema, prev column: " << prev_col_pb.DebugString()
1171
0
                           << " current column: " << curr_col_pb.DebugString();
1172
0
                        LOG(WARNING) << ss.str();
1173
0
                        response->mutable_status()->set_status_code(TStatusCode::ILLEGAL_STATE);
1174
0
                        response->mutable_status()->add_error_msgs(ss.str());
1175
0
                        return;
1176
0
                    }
1177
0
                }
1178
0
            }
1179
0
        }
1180
1181
0
        if (filter_set.size() > 1) {
1182
            // consistecy check failed
1183
0
            std::stringstream ss;
1184
0
            ss << "consistency check failed: index{" << index_id << "}"
1185
0
               << "got inconsistent schema";
1186
0
            LOG(WARNING) << ss.str();
1187
0
            response->mutable_status()->set_status_code(TStatusCode::ILLEGAL_STATE);
1188
0
            response->mutable_status()->add_error_msgs(ss.str());
1189
0
            return;
1190
0
        }
1191
        // consistency check passed, use the first tablet to be the representative
1192
0
        TabletSharedPtr tablet = tablet_mgr->get_tablet(tablet_ids[0]);
1193
0
        const auto& columns = tablet->tablet_schema()->columns();
1194
0
        auto entry = response->add_entries();
1195
0
        entry->set_index_id(index_id);
1196
0
        auto col_name_to_id = entry->mutable_col_name_to_id();
1197
0
        for (const auto& column : columns) {
1198
0
            (*col_name_to_id)[column->name()] = column->unique_id();
1199
0
        }
1200
0
    }
1201
0
    response->mutable_status()->set_status_code(TStatusCode::OK);
1202
0
}
1203
1204
template <class RPCResponse>
1205
struct AsyncRPCContext {
1206
    RPCResponse response;
1207
    brpc::Controller cntl;
1208
    brpc::CallId cid;
1209
};
1210
1211
void PInternalService::fetch_remote_tablet_schema(google::protobuf::RpcController* controller,
1212
                                                  const PFetchRemoteSchemaRequest* request,
1213
                                                  PFetchRemoteSchemaResponse* response,
1214
52
                                                  google::protobuf::Closure* done) {
1215
52
    bool ret = _heavy_work_pool.try_offer([request, response, done]() {
1216
52
        brpc::ClosureGuard closure_guard(done);
1217
52
        Status st = Status::OK();
1218
52
        std::shared_ptr<MemTrackerLimiter> mem_tracker = MemTrackerLimiter::create_shared(
1219
52
                MemTrackerLimiter::Type::OTHER,
1220
52
                fmt::format("InternalService::fetch_remote_tablet_schema"));
1221
52
        SCOPED_ATTACH_TASK(mem_tracker);
1222
52
        if (request->is_coordinator()) {
1223
            // Spawn rpc request to none coordinator nodes, and finally merge them all
1224
26
            PFetchRemoteSchemaRequest remote_request(*request);
1225
            // set it none coordinator to get merged schema
1226
26
            remote_request.set_is_coordinator(false);
1227
26
            using PFetchRemoteTabletSchemaRpcContext = AsyncRPCContext<PFetchRemoteSchemaResponse>;
1228
26
            std::vector<PFetchRemoteTabletSchemaRpcContext> rpc_contexts(
1229
26
                    request->tablet_location_size());
1230
52
            for (int i = 0; i < request->tablet_location_size(); ++i) {
1231
26
                std::string host = request->tablet_location(i).host();
1232
26
                int32_t brpc_port = request->tablet_location(i).brpc_port();
1233
26
                std::shared_ptr<PBackendService_Stub> stub(
1234
26
                        ExecEnv::GetInstance()->brpc_internal_client_cache()->get_client(
1235
26
                                host, brpc_port));
1236
26
                if (stub == nullptr) {
1237
0
                    LOG(WARNING) << "Failed to init rpc to " << host << ":" << brpc_port;
1238
0
                    st = Status::InternalError("Failed to init rpc to {}:{}", host, brpc_port);
1239
0
                    continue;
1240
0
                }
1241
26
                rpc_contexts[i].cid = rpc_contexts[i].cntl.call_id();
1242
26
                rpc_contexts[i].cntl.set_timeout_ms(config::fetch_remote_schema_rpc_timeout_ms);
1243
26
                stub->fetch_remote_tablet_schema(&rpc_contexts[i].cntl, &remote_request,
1244
26
                                                 &rpc_contexts[i].response, brpc::DoNothing());
1245
26
            }
1246
26
            std::vector<TabletSchemaSPtr> schemas;
1247
26
            for (auto& rpc_context : rpc_contexts) {
1248
26
                brpc::Join(rpc_context.cid);
1249
26
                if (!st.ok()) {
1250
                    // make sure all flying rpc request is joined
1251
0
                    continue;
1252
0
                }
1253
26
                if (rpc_context.cntl.Failed()) {
1254
0
                    LOG(WARNING) << "fetch_remote_tablet_schema rpc err:"
1255
0
                                 << rpc_context.cntl.ErrorText();
1256
0
                    ExecEnv::GetInstance()->brpc_internal_client_cache()->erase(
1257
0
                            rpc_context.cntl.remote_side());
1258
0
                    st = Status::InternalError("fetch_remote_tablet_schema rpc err: {}",
1259
0
                                               rpc_context.cntl.ErrorText());
1260
0
                }
1261
26
                if (rpc_context.response.status().status_code() != 0) {
1262
0
                    st = Status::create(rpc_context.response.status());
1263
0
                }
1264
26
                if (rpc_context.response.has_merged_schema()) {
1265
26
                    TabletSchemaSPtr schema = std::make_shared<TabletSchema>();
1266
26
                    schema->init_from_pb(rpc_context.response.merged_schema());
1267
26
                    schemas.push_back(schema);
1268
26
                }
1269
26
            }
1270
26
            if (!schemas.empty() && st.ok()) {
1271
                // merge all
1272
26
                TabletSchemaSPtr merged_schema;
1273
26
                st = variant_util::get_least_common_schema(schemas, nullptr, merged_schema);
1274
26
                if (!st.ok()) {
1275
0
                    LOG(WARNING) << "Failed to get least common schema: " << st.to_string();
1276
0
                    st = Status::InternalError("Failed to get least common schema: {}",
1277
0
                                               st.to_string());
1278
0
                }
1279
26
                VLOG_DEBUG << "dump schema:" << merged_schema->dump_structure();
1280
26
                merged_schema->reserve_extracted_columns();
1281
26
                merged_schema->to_schema_pb(response->mutable_merged_schema());
1282
26
            }
1283
26
            st.to_protobuf(response->mutable_status());
1284
26
            return;
1285
26
        } else {
1286
            // This is not a coordinator, get it's tablet and merge schema
1287
26
            std::vector<int64_t> target_tablets;
1288
26
            for (int i = 0; i < request->tablet_location_size(); ++i) {
1289
26
                const auto& location = request->tablet_location(i);
1290
26
                auto backend = BackendOptions::get_local_backend();
1291
                // If this is the target backend
1292
26
                if (backend.host == location.host() && config::brpc_port == location.brpc_port()) {
1293
26
                    target_tablets.assign(location.tablet_id().begin(), location.tablet_id().end());
1294
26
                    break;
1295
26
                }
1296
26
            }
1297
26
            if (!target_tablets.empty()) {
1298
26
                std::vector<TabletSchemaSPtr> tablet_schemas;
1299
1.33k
                for (int64_t tablet_id : target_tablets) {
1300
1.33k
                    auto res = ExecEnv::get_tablet(tablet_id);
1301
1.33k
                    if (!res.has_value()) {
1302
                        // just ignore
1303
0
                        LOG(WARNING) << "tablet does not exist, tablet id is " << tablet_id;
1304
0
                        continue;
1305
0
                    }
1306
1.33k
                    auto tablet = res.value();
1307
1.33k
                    auto rowsets = tablet->get_snapshot_rowset();
1308
1.33k
                    auto schema =
1309
1.33k
                            variant_util::VariantCompactionUtil::calculate_variant_extended_schema(
1310
1.33k
                                    rowsets, tablet->tablet_schema());
1311
1.33k
                    tablet_schemas.push_back(schema);
1312
1.33k
                }
1313
26
                if (!tablet_schemas.empty()) {
1314
                    // merge all
1315
26
                    TabletSchemaSPtr merged_schema;
1316
26
                    st = variant_util::get_least_common_schema(tablet_schemas, nullptr,
1317
26
                                                               merged_schema);
1318
26
                    if (!st.ok()) {
1319
0
                        LOG(WARNING) << "Failed to get least common schema: " << st.to_string();
1320
0
                        st = Status::InternalError("Failed to get least common schema: {}",
1321
0
                                                   st.to_string());
1322
0
                    }
1323
26
                    merged_schema->to_schema_pb(response->mutable_merged_schema());
1324
26
                    VLOG_DEBUG << "dump schema:" << merged_schema->dump_structure();
1325
26
                }
1326
26
            }
1327
26
            st.to_protobuf(response->mutable_status());
1328
26
        }
1329
52
    });
1330
52
    if (!ret) {
1331
0
        offer_failed(response, done, _heavy_work_pool);
1332
0
    }
1333
52
}
1334
1335
void PInternalService::report_stream_load_status(google::protobuf::RpcController* controller,
1336
                                                 const PReportStreamLoadStatusRequest* request,
1337
                                                 PReportStreamLoadStatusResponse* response,
1338
0
                                                 google::protobuf::Closure* done) {
1339
0
    TUniqueId load_id;
1340
0
    load_id.__set_hi(request->load_id().hi());
1341
0
    load_id.__set_lo(request->load_id().lo());
1342
0
    Status st = Status::OK();
1343
0
    auto stream_load_ctx = _exec_env->new_load_stream_mgr()->get(load_id);
1344
0
    if (!stream_load_ctx) {
1345
0
        st = Status::InternalError("unknown stream load id: {}", UniqueId(load_id).to_string());
1346
0
    }
1347
0
    stream_load_ctx->load_status_promise.set_value(st);
1348
0
    st.to_protobuf(response->mutable_status());
1349
0
}
1350
1351
void PInternalService::get_info(google::protobuf::RpcController* controller,
1352
                                const PProxyRequest* request, PProxyResult* response,
1353
1.60k
                                google::protobuf::Closure* done) {
1354
1.60k
    bool ret = _exec_env->routine_load_task_executor()->get_thread_pool().submit_func([this,
1355
1.60k
                                                                                       request,
1356
1.60k
                                                                                       response,
1357
1.60k
                                                                                       done]() {
1358
1.60k
        brpc::ClosureGuard closure_guard(done);
1359
        // PProxyRequest is defined in gensrc/proto/internal_service.proto
1360
        // Currently it supports 2 kinds of requests:
1361
        // 1. get all kafka partition ids for given topic
1362
        // 2. get all kafka partition offsets for given topic and timestamp.
1363
1.60k
        int timeout_ms = request->has_timeout_secs() ? request->timeout_secs() * 1000 : 60 * 1000;
1364
1.60k
        if (request->has_kafka_meta_request()) {
1365
1.60k
            const PKafkaMetaProxyRequest& kafka_request = request->kafka_meta_request();
1366
1.60k
            if (!kafka_request.offset_flags().empty()) {
1367
69
                std::vector<PIntegerPair> partition_offsets;
1368
69
                Status st = _exec_env->routine_load_task_executor()
1369
69
                                    ->get_kafka_real_offsets_for_partitions(
1370
69
                                            request->kafka_meta_request(), &partition_offsets,
1371
69
                                            timeout_ms);
1372
69
                if (st.ok()) {
1373
69
                    PKafkaPartitionOffsets* part_offsets = response->mutable_partition_offsets();
1374
69
                    for (const auto& entry : partition_offsets) {
1375
69
                        PIntegerPair* res = part_offsets->add_offset_times();
1376
69
                        res->set_key(entry.key());
1377
69
                        res->set_val(entry.val());
1378
69
                    }
1379
69
                }
1380
69
                st.to_protobuf(response->mutable_status());
1381
69
                return;
1382
1.53k
            } else if (!kafka_request.partition_id_for_latest_offsets().empty()) {
1383
                // get latest offsets for specified partition ids
1384
1.45k
                std::vector<PIntegerPair> partition_offsets;
1385
1.45k
                Status st = _exec_env->routine_load_task_executor()
1386
1.45k
                                    ->get_kafka_latest_offsets_for_partitions(
1387
1.45k
                                            request->kafka_meta_request(), &partition_offsets,
1388
1.45k
                                            timeout_ms);
1389
1.45k
                if (st.ok()) {
1390
1.45k
                    PKafkaPartitionOffsets* part_offsets = response->mutable_partition_offsets();
1391
1.45k
                    for (const auto& entry : partition_offsets) {
1392
1.45k
                        PIntegerPair* res = part_offsets->add_offset_times();
1393
1.45k
                        res->set_key(entry.key());
1394
1.45k
                        res->set_val(entry.val());
1395
1.45k
                    }
1396
1.45k
                }
1397
1.45k
                st.to_protobuf(response->mutable_status());
1398
1.45k
                return;
1399
1.45k
            } else if (!kafka_request.offset_times().empty()) {
1400
                // if offset_times() has elements, which means this request is to get offset by timestamp.
1401
1
                std::vector<PIntegerPair> partition_offsets;
1402
1
                Status st = _exec_env->routine_load_task_executor()
1403
1
                                    ->get_kafka_partition_offsets_for_times(
1404
1
                                            request->kafka_meta_request(), &partition_offsets,
1405
1
                                            timeout_ms);
1406
1
                if (st.ok()) {
1407
1
                    PKafkaPartitionOffsets* part_offsets = response->mutable_partition_offsets();
1408
1
                    for (const auto& entry : partition_offsets) {
1409
1
                        PIntegerPair* res = part_offsets->add_offset_times();
1410
1
                        res->set_key(entry.key());
1411
1
                        res->set_val(entry.val());
1412
1
                    }
1413
1
                }
1414
1
                st.to_protobuf(response->mutable_status());
1415
1
                return;
1416
78
            } else {
1417
                // get partition ids of topic
1418
78
                std::vector<int32_t> partition_ids;
1419
78
                Status st = _exec_env->routine_load_task_executor()->get_kafka_partition_meta(
1420
78
                        request->kafka_meta_request(), &partition_ids);
1421
78
                if (st.ok()) {
1422
75
                    PKafkaMetaProxyResult* kafka_result = response->mutable_kafka_meta_result();
1423
75
                    for (int32_t id : partition_ids) {
1424
75
                        kafka_result->add_partition_ids(id);
1425
75
                    }
1426
75
                }
1427
78
                st.to_protobuf(response->mutable_status());
1428
78
                return;
1429
78
            }
1430
1.60k
        }
1431
0
        if (request->has_kinesis_meta_request()) {
1432
0
            std::vector<std::string> shard_ids;
1433
0
            Status st = _exec_env->routine_load_task_executor()->get_kinesis_shard_meta(
1434
0
                    request->kinesis_meta_request(), &shard_ids);
1435
0
            if (st.ok()) {
1436
0
                PKinesisMetaProxyResult* kinesis_result = response->mutable_kinesis_meta_result();
1437
0
                for (const auto& shard_id : shard_ids) {
1438
0
                    kinesis_result->add_shard_ids(shard_id);
1439
0
                }
1440
0
            }
1441
0
            st.to_protobuf(response->mutable_status());
1442
0
            return;
1443
0
        }
1444
0
        Status::OK().to_protobuf(response->mutable_status());
1445
0
    });
1446
1.60k
    if (!ret) {
1447
0
        offer_failed(response, done, _heavy_work_pool);
1448
0
        return;
1449
0
    }
1450
1.60k
}
1451
1452
void PInternalService::update_cache(google::protobuf::RpcController* controller,
1453
                                    const PUpdateCacheRequest* request, PCacheResponse* response,
1454
68.0k
                                    google::protobuf::Closure* done) {
1455
68.0k
    bool ret = _light_work_pool.try_offer([this, request, response, done]() {
1456
68.0k
        brpc::ClosureGuard closure_guard(done);
1457
68.0k
        _exec_env->result_cache()->update(request, response);
1458
68.0k
    });
1459
68.0k
    if (!ret) {
1460
0
        offer_failed(response, done, _light_work_pool);
1461
0
        return;
1462
0
    }
1463
68.0k
}
1464
1465
void PInternalService::fetch_cache(google::protobuf::RpcController* controller,
1466
                                   const PFetchCacheRequest* request, PFetchCacheResult* result,
1467
3.52k
                                   google::protobuf::Closure* done) {
1468
3.52k
    bool ret = _light_work_pool.try_offer([this, request, result, done]() {
1469
3.52k
        brpc::ClosureGuard closure_guard(done);
1470
3.52k
        _exec_env->result_cache()->fetch(request, result);
1471
3.52k
    });
1472
3.52k
    if (!ret) {
1473
0
        offer_failed(result, done, _light_work_pool);
1474
0
        return;
1475
0
    }
1476
3.52k
}
1477
1478
void PInternalService::clear_cache(google::protobuf::RpcController* controller,
1479
                                   const PClearCacheRequest* request, PCacheResponse* response,
1480
0
                                   google::protobuf::Closure* done) {
1481
0
    bool ret = _light_work_pool.try_offer([this, request, response, done]() {
1482
0
        brpc::ClosureGuard closure_guard(done);
1483
0
        _exec_env->result_cache()->clear(request, response);
1484
0
    });
1485
0
    if (!ret) {
1486
0
        offer_failed(response, done, _light_work_pool);
1487
0
        return;
1488
0
    }
1489
0
}
1490
1491
void PInternalService::merge_filter(::google::protobuf::RpcController* controller,
1492
                                    const ::doris::PMergeFilterRequest* request,
1493
                                    ::doris::PMergeFilterResponse* response,
1494
2.51k
                                    ::google::protobuf::Closure* done) {
1495
2.52k
    bool ret = _light_work_pool.try_offer([this, controller, request, response, done]() {
1496
2.52k
        signal::SignalTaskIdKeeper keeper(request->query_id());
1497
2.52k
        brpc::ClosureGuard closure_guard(done);
1498
2.52k
        auto attachment = static_cast<brpc::Controller*>(controller)->request_attachment();
1499
2.52k
        butil::IOBufAsZeroCopyInputStream zero_copy_input_stream(attachment);
1500
2.52k
        Status st;
1501
2.52k
        try {
1502
2.52k
            st = _exec_env->fragment_mgr()->merge_filter(request, &zero_copy_input_stream);
1503
2.52k
        } catch (Exception& e) {
1504
0
            st = e.to_status();
1505
0
        }
1506
2.52k
        st.to_protobuf(response->mutable_status());
1507
2.52k
    });
1508
2.51k
    if (!ret) {
1509
0
        offer_failed(response, done, _light_work_pool);
1510
0
        return;
1511
0
    }
1512
2.51k
}
1513
1514
void PInternalService::send_filter_size(::google::protobuf::RpcController* controller,
1515
                                        const ::doris::PSendFilterSizeRequest* request,
1516
                                        ::doris::PSendFilterSizeResponse* response,
1517
171
                                        ::google::protobuf::Closure* done) {
1518
171
    bool ret = _light_work_pool.try_offer([this, request, response, done]() {
1519
171
        signal::SignalTaskIdKeeper keeper(request->query_id());
1520
171
        brpc::ClosureGuard closure_guard(done);
1521
171
        Status st;
1522
171
        try {
1523
171
            st = _exec_env->fragment_mgr()->send_filter_size(request);
1524
171
        } catch (Exception& e) {
1525
0
            st = e.to_status();
1526
0
        }
1527
171
        st.to_protobuf(response->mutable_status());
1528
171
    });
1529
171
    if (!ret) {
1530
0
        offer_failed(response, done, _light_work_pool);
1531
0
        return;
1532
0
    }
1533
171
}
1534
1535
void PInternalService::sync_filter_size(::google::protobuf::RpcController* controller,
1536
                                        const ::doris::PSyncFilterSizeRequest* request,
1537
                                        ::doris::PSyncFilterSizeResponse* response,
1538
171
                                        ::google::protobuf::Closure* done) {
1539
171
    bool ret = _light_work_pool.try_offer([this, request, response, done]() {
1540
171
        signal::SignalTaskIdKeeper keeper(request->query_id());
1541
171
        brpc::ClosureGuard closure_guard(done);
1542
171
        Status st;
1543
171
        try {
1544
171
            st = _exec_env->fragment_mgr()->sync_filter_size(request);
1545
171
        } catch (Exception& e) {
1546
0
            st = e.to_status();
1547
0
        }
1548
171
        st.to_protobuf(response->mutable_status());
1549
171
    });
1550
171
    if (!ret) {
1551
0
        offer_failed(response, done, _light_work_pool);
1552
0
        return;
1553
0
    }
1554
171
}
1555
1556
void PInternalService::apply_filterv2(::google::protobuf::RpcController* controller,
1557
                                      const ::doris::PPublishFilterRequestV2* request,
1558
                                      ::doris::PPublishFilterResponse* response,
1559
1.76k
                                      ::google::protobuf::Closure* done) {
1560
1.76k
    bool ret = _light_work_pool.try_offer([this, controller, request, response, done]() {
1561
1.76k
        signal::SignalTaskIdKeeper keeper(request->query_id());
1562
1.76k
        brpc::ClosureGuard closure_guard(done);
1563
1.76k
        const butil::IOBuf& request_attachment =
1564
1.76k
                static_cast<brpc::Controller*>(controller)->request_attachment();
1565
1.76k
        butil::IOBuf apply_attachment = request_attachment;
1566
1.76k
        butil::IOBuf forward_attachment = request_attachment;
1567
1.76k
        butil::IOBufAsZeroCopyInputStream zero_copy_input_stream(apply_attachment);
1568
1.76k
        VLOG_NOTICE << "rpc apply_filterv2 recv";
1569
1.76k
        Status st;
1570
1.76k
        try {
1571
1.76k
            st = _exec_env->fragment_mgr()->apply_filterv2(request, &zero_copy_input_stream);
1572
1.76k
        } catch (Exception& e) {
1573
0
            st = e.to_status();
1574
0
        }
1575
1.76k
        if (!st.ok()) {
1576
0
            LOG(WARNING) << "apply filter meet error: " << st.to_string();
1577
0
        }
1578
1.76k
        std::weak_ptr<QueryContext> forward_ctx;
1579
1.76k
        if (auto query_ctx = _exec_env->fragment_mgr()->get_query_ctx(
1580
1.76k
                    UniqueId(request->query_id()).to_thrift())) {
1581
1.75k
            if (!query_ctx->ignore_runtime_filter_error()) {
1582
1.74k
                forward_ctx = query_ctx;
1583
1.74k
            }
1584
1.75k
        }
1585
1.76k
        Status forward_st = forward_runtime_filter(*request, forward_attachment, forward_ctx);
1586
1.76k
        if (!forward_st.ok()) {
1587
0
            LOG(WARNING) << "forward runtime filter meet error: " << forward_st.to_string();
1588
0
            if (st.ok()) {
1589
0
                st = std::move(forward_st);
1590
0
            }
1591
0
        }
1592
1.76k
        st.to_protobuf(response->mutable_status());
1593
1.76k
    });
1594
1.76k
    if (!ret) {
1595
0
        offer_failed(response, done, _light_work_pool);
1596
0
        return;
1597
0
    }
1598
1.76k
}
1599
1600
void PInternalService::send_data(google::protobuf::RpcController* controller,
1601
                                 const PSendDataRequest* request, PSendDataResult* response,
1602
45
                                 google::protobuf::Closure* done) {
1603
45
    bool ret = _heavy_work_pool.try_offer([this, request, response, done]() {
1604
45
        brpc::ClosureGuard closure_guard(done);
1605
45
        TUniqueId load_id;
1606
45
        load_id.hi = request->load_id().hi();
1607
45
        load_id.lo = request->load_id().lo();
1608
        // On 1.2.3 we add load id to send data request and using load id to get pipe
1609
45
        auto stream_load_ctx = _exec_env->new_load_stream_mgr()->get(load_id);
1610
45
        if (stream_load_ctx == nullptr) {
1611
0
            response->mutable_status()->set_status_code(1);
1612
0
            response->mutable_status()->add_error_msgs("could not find stream load context");
1613
45
        } else {
1614
45
            auto pipe = stream_load_ctx->pipe;
1615
160
            for (int i = 0; i < request->data_size(); ++i) {
1616
115
                std::unique_ptr<PDataRow> row(new PDataRow());
1617
115
                row->CopyFrom(request->data(i));
1618
115
                Status s = pipe->append(std::move(row));
1619
115
                if (!s.ok()) {
1620
0
                    response->mutable_status()->set_status_code(1);
1621
0
                    response->mutable_status()->add_error_msgs(s.to_string());
1622
0
                    return;
1623
0
                }
1624
115
            }
1625
45
            response->mutable_status()->set_status_code(0);
1626
45
        }
1627
45
    });
1628
45
    if (!ret) {
1629
0
        offer_failed(response, done, _heavy_work_pool);
1630
0
        return;
1631
0
    }
1632
45
}
1633
1634
void PInternalService::commit(google::protobuf::RpcController* controller,
1635
                              const PCommitRequest* request, PCommitResult* response,
1636
45
                              google::protobuf::Closure* done) {
1637
45
    bool ret = _heavy_work_pool.try_offer([this, request, response, done]() {
1638
45
        brpc::ClosureGuard closure_guard(done);
1639
45
        TUniqueId load_id;
1640
45
        load_id.hi = request->load_id().hi();
1641
45
        load_id.lo = request->load_id().lo();
1642
1643
45
        auto stream_load_ctx = _exec_env->new_load_stream_mgr()->get(load_id);
1644
45
        if (stream_load_ctx == nullptr) {
1645
0
            response->mutable_status()->set_status_code(1);
1646
0
            response->mutable_status()->add_error_msgs("could not find stream load context");
1647
45
        } else {
1648
45
            static_cast<void>(stream_load_ctx->pipe->finish());
1649
45
            response->mutable_status()->set_status_code(0);
1650
45
        }
1651
45
    });
1652
45
    if (!ret) {
1653
0
        offer_failed(response, done, _heavy_work_pool);
1654
0
        return;
1655
0
    }
1656
45
}
1657
1658
void PInternalService::rollback(google::protobuf::RpcController* controller,
1659
                                const PRollbackRequest* request, PRollbackResult* response,
1660
6
                                google::protobuf::Closure* done) {
1661
6
    bool ret = _heavy_work_pool.try_offer([this, request, response, done]() {
1662
6
        brpc::ClosureGuard closure_guard(done);
1663
6
        TUniqueId load_id;
1664
6
        load_id.hi = request->load_id().hi();
1665
6
        load_id.lo = request->load_id().lo();
1666
6
        auto stream_load_ctx = _exec_env->new_load_stream_mgr()->get(load_id);
1667
6
        if (stream_load_ctx == nullptr) {
1668
0
            response->mutable_status()->set_status_code(1);
1669
0
            response->mutable_status()->add_error_msgs("could not find stream load context");
1670
6
        } else {
1671
6
            stream_load_ctx->pipe->cancel("rollback");
1672
6
            response->mutable_status()->set_status_code(0);
1673
6
        }
1674
6
    });
1675
6
    if (!ret) {
1676
0
        offer_failed(response, done, _heavy_work_pool);
1677
0
        return;
1678
0
    }
1679
6
}
1680
1681
void PInternalService::fold_constant_expr(google::protobuf::RpcController* controller,
1682
                                          const PConstantExprRequest* request,
1683
                                          PConstantExprResult* response,
1684
1.70k
                                          google::protobuf::Closure* done) {
1685
1.70k
    bool ret = _light_work_pool.try_offer([request, response, done]() {
1686
1.70k
        brpc::ClosureGuard closure_guard(done);
1687
1.70k
        TFoldConstantParams t_request;
1688
1.70k
        Status st = Status::OK();
1689
1.70k
        {
1690
1.70k
            const uint8_t* buf = (const uint8_t*)request->request().data();
1691
1.70k
            uint32_t len = request->request().size();
1692
1.70k
            st = deserialize_thrift_msg(buf, &len, false, &t_request);
1693
1.70k
        }
1694
1.70k
        if (!st.ok()) {
1695
0
            LOG(WARNING) << "exec fold constant expr failed, errmsg=" << st
1696
0
                         << " .and query_id_is: " << t_request.query_id;
1697
0
            st.to_protobuf(response->mutable_status());
1698
0
            return;
1699
0
        }
1700
1.70k
        auto fold_func = [&]() -> Status {
1701
1.70k
            std::unique_ptr<FoldConstantExecutor> fold_executor =
1702
1.70k
                    std::make_unique<FoldConstantExecutor>();
1703
1.70k
            RETURN_IF_ERROR_OR_CATCH_EXCEPTION(
1704
1.70k
                    fold_executor->fold_constant_vexpr(t_request, response));
1705
1.16k
            return Status::OK();
1706
1.70k
        };
1707
1.70k
        st = fold_func();
1708
1.70k
        if (!st.ok()) {
1709
533
            LOG(WARNING) << "exec fold constant expr failed, errmsg=" << st
1710
533
                         << " .and query_id_is: " << t_request.query_id;
1711
533
        }
1712
1.70k
        st.to_protobuf(response->mutable_status());
1713
1.70k
    });
1714
1.70k
    if (!ret) {
1715
0
        offer_failed(response, done, _light_work_pool);
1716
0
        return;
1717
0
    }
1718
1.70k
}
1719
1720
void PInternalService::transmit_rec_cte_block(google::protobuf::RpcController* controller,
1721
                                              const PTransmitRecCTEBlockParams* request,
1722
                                              PTransmitRecCTEBlockResult* response,
1723
4.26k
                                              google::protobuf::Closure* done) {
1724
4.26k
    bool ret = _light_work_pool.try_offer([this, request, response, done]() {
1725
4.26k
        brpc::ClosureGuard closure_guard(done);
1726
4.26k
        auto st = _exec_env->fragment_mgr()->transmit_rec_cte_block(
1727
4.26k
                UniqueId(request->query_id()).to_thrift(),
1728
4.26k
                UniqueId(request->fragment_instance_id()).to_thrift(), request->node_id(),
1729
4.26k
                request->blocks(), request->eos());
1730
4.26k
        st.to_protobuf(response->mutable_status());
1731
4.26k
    });
1732
4.26k
    if (!ret) {
1733
0
        offer_failed(response, done, _light_work_pool);
1734
0
        return;
1735
0
    }
1736
4.26k
}
1737
1738
void PInternalService::rerun_fragment(google::protobuf::RpcController* controller,
1739
                                      const PRerunFragmentParams* request,
1740
                                      PRerunFragmentResult* response,
1741
10.8k
                                      google::protobuf::Closure* done) {
1742
10.8k
    bool ret = _light_work_pool.try_offer([this, request, response, done]() {
1743
        // Use shared_ptr<ClosureGuard> so we can transfer ownership to the PFC.
1744
        // For wait_for_destroy/final_close, the guard is stored in the PFC and the RPC
1745
        // response is deferred until the PFC is fully destroyed. For rebuild/submit,
1746
        // the guard fires immediately when this lambda returns.
1747
10.8k
        std::shared_ptr<brpc::ClosureGuard> closure_guard =
1748
10.8k
                std::make_shared<brpc::ClosureGuard>(done);
1749
10.8k
        auto st = _exec_env->fragment_mgr()->rerun_fragment(
1750
10.8k
                closure_guard, UniqueId(request->query_id()).to_thrift(), request->fragment_id(),
1751
10.8k
                request->stage());
1752
10.8k
        st.to_protobuf(response->mutable_status());
1753
10.8k
    });
1754
10.8k
    if (!ret) {
1755
0
        offer_failed(response, done, _light_work_pool);
1756
0
        return;
1757
0
    }
1758
10.8k
}
1759
1760
void PInternalService::reset_global_rf(google::protobuf::RpcController* controller,
1761
                                       const PResetGlobalRfParams* request,
1762
                                       PResetGlobalRfResult* response,
1763
2.06k
                                       google::protobuf::Closure* done) {
1764
2.06k
    bool ret = _light_work_pool.try_offer([this, request, response, done]() {
1765
2.06k
        brpc::ClosureGuard closure_guard(done);
1766
2.06k
        auto st = _exec_env->fragment_mgr()->reset_global_rf(
1767
2.06k
                UniqueId(request->query_id()).to_thrift(), request->filter_ids());
1768
2.06k
        st.to_protobuf(response->mutable_status());
1769
2.06k
    });
1770
2.06k
    if (!ret) {
1771
0
        offer_failed(response, done, _light_work_pool);
1772
0
        return;
1773
0
    }
1774
2.06k
}
1775
1776
void PInternalService::transmit_block(google::protobuf::RpcController* controller,
1777
                                      const PTransmitDataParams* request,
1778
                                      PTransmitDataResult* response,
1779
2.43M
                                      google::protobuf::Closure* done) {
1780
2.43M
    int64_t receive_time = GetCurrentTimeNanos();
1781
2.47M
    if (config::enable_bthread_transmit_block) {
1782
2.47M
        response->set_receive_time(receive_time);
1783
        // under high concurrency, thread pool will have a lot of lock contention.
1784
        // May offer failed to the thread pool, so that we should avoid using thread
1785
        // pool here.
1786
2.47M
        _transmit_block(controller, request, response, done, Status::OK(), 0);
1787
18.4E
    } else {
1788
18.4E
        bool ret = _light_work_pool.try_offer([this, controller, request, response, done,
1789
18.4E
                                               receive_time]() {
1790
0
            response->set_receive_time(receive_time);
1791
            // Sometimes transmit block function is the last owner of PlanFragmentExecutor
1792
            // It will release the object. And the object maybe a JNIContext.
1793
            // JNIContext will hold some TLS object. It could not work correctly under bthread
1794
            // Context. So that put the logic into pthread.
1795
            // But this is rarely happens, so this config is disabled by default.
1796
0
            _transmit_block(controller, request, response, done, Status::OK(),
1797
0
                            GetCurrentTimeNanos() - receive_time);
1798
0
        });
1799
18.4E
        if (!ret) {
1800
0
            offer_failed(response, done, _light_work_pool);
1801
0
            return;
1802
0
        }
1803
18.4E
    }
1804
2.43M
}
1805
1806
void PInternalService::transmit_block_by_http(google::protobuf::RpcController* controller,
1807
                                              const PEmptyRequest* request,
1808
                                              PTransmitDataResult* response,
1809
0
                                              google::protobuf::Closure* done) {
1810
0
    int64_t receive_time = GetCurrentTimeNanos();
1811
0
    bool ret = _heavy_work_pool.try_offer([this, controller, response, done, receive_time]() {
1812
0
        PTransmitDataParams* new_request = new PTransmitDataParams();
1813
0
        google::protobuf::Closure* new_done =
1814
0
                new NewHttpClosure<PTransmitDataParams>(new_request, done);
1815
0
        brpc::Controller* cntl = static_cast<brpc::Controller*>(controller);
1816
0
        Status st =
1817
0
                attachment_extract_request_contain_block<PTransmitDataParams>(new_request, cntl);
1818
0
        _transmit_block(controller, new_request, response, new_done, st,
1819
0
                        GetCurrentTimeNanos() - receive_time);
1820
0
    });
1821
0
    if (!ret) {
1822
0
        offer_failed(response, done, _heavy_work_pool);
1823
0
        return;
1824
0
    }
1825
0
}
1826
1827
void PInternalService::_transmit_block(google::protobuf::RpcController* controller,
1828
                                       const PTransmitDataParams* request,
1829
                                       PTransmitDataResult* response,
1830
                                       google::protobuf::Closure* done, const Status& extract_st,
1831
2.42M
                                       const int64_t wait_for_worker) {
1832
2.47M
    if (request->has_query_id()) {
1833
18.4E
        VLOG_ROW << "transmit block: fragment_instance_id=" << print_id(request->finst_id())
1834
18.4E
                 << " query_id=" << print_id(request->query_id()) << " node=" << request->node_id();
1835
2.47M
    }
1836
1837
    // The response is accessed when done->Run is called in transmit_block(),
1838
    // give response a default value to avoid null pointers in high concurrency.
1839
2.42M
    Status st;
1840
2.44M
    if (extract_st.ok()) {
1841
2.44M
        st = _exec_env->vstream_mgr()->transmit_block(request, &done, wait_for_worker);
1842
2.44M
        if (!st.ok() && !st.is<END_OF_FILE>()) {
1843
0
            LOG(WARNING) << "transmit_block failed, message=" << st
1844
0
                         << ", fragment_instance_id=" << print_id(request->finst_id())
1845
0
                         << ", node=" << request->node_id()
1846
0
                         << ", from sender_id: " << request->sender_id()
1847
0
                         << ", be_number: " << request->be_number()
1848
0
                         << ", packet_seq: " << request->packet_seq();
1849
0
        }
1850
18.4E
    } else {
1851
18.4E
        st = extract_st;
1852
18.4E
    }
1853
2.47M
    if (done != nullptr) {
1854
2.47M
        st.to_protobuf(response->mutable_status());
1855
2.47M
        done->Run();
1856
2.47M
    }
1857
2.42M
}
1858
1859
void PInternalService::check_rpc_channel(google::protobuf::RpcController* controller,
1860
                                         const PCheckRPCChannelRequest* request,
1861
                                         PCheckRPCChannelResponse* response,
1862
0
                                         google::protobuf::Closure* done) {
1863
0
    bool ret = _light_work_pool.try_offer([request, response, done]() {
1864
0
        brpc::ClosureGuard closure_guard(done);
1865
0
        response->mutable_status()->set_status_code(0);
1866
0
        if (request->data().size() != request->size()) {
1867
0
            std::stringstream ss;
1868
0
            ss << "data size not same, expected: " << request->size()
1869
0
               << ", actual: " << request->data().size();
1870
0
            response->mutable_status()->add_error_msgs(ss.str());
1871
0
            response->mutable_status()->set_status_code(1);
1872
1873
0
        } else {
1874
0
            Md5Digest digest;
1875
0
            digest.update(static_cast<const void*>(request->data().c_str()),
1876
0
                          request->data().size());
1877
0
            digest.digest();
1878
0
            if (!iequal(digest.hex(), request->md5())) {
1879
0
                std::stringstream ss;
1880
0
                ss << "md5 not same, expected: " << request->md5() << ", actual: " << digest.hex();
1881
0
                response->mutable_status()->add_error_msgs(ss.str());
1882
0
                response->mutable_status()->set_status_code(1);
1883
0
            }
1884
0
        }
1885
0
    });
1886
0
    if (!ret) {
1887
0
        offer_failed(response, done, _light_work_pool);
1888
0
        return;
1889
0
    }
1890
0
}
1891
1892
void PInternalService::reset_rpc_channel(google::protobuf::RpcController* controller,
1893
                                         const PResetRPCChannelRequest* request,
1894
                                         PResetRPCChannelResponse* response,
1895
0
                                         google::protobuf::Closure* done) {
1896
0
    bool ret = _light_work_pool.try_offer([request, response, done]() {
1897
0
        brpc::ClosureGuard closure_guard(done);
1898
0
        response->mutable_status()->set_status_code(0);
1899
0
        if (request->all()) {
1900
0
            int size = ExecEnv::GetInstance()->brpc_internal_client_cache()->size();
1901
0
            if (size > 0) {
1902
0
                std::vector<std::string> endpoints;
1903
0
                ExecEnv::GetInstance()->brpc_internal_client_cache()->get_all(&endpoints);
1904
0
                ExecEnv::GetInstance()->brpc_internal_client_cache()->clear();
1905
0
                *response->mutable_channels() = {endpoints.begin(), endpoints.end()};
1906
0
            }
1907
0
        } else {
1908
0
            for (const std::string& endpoint : request->endpoints()) {
1909
0
                if (!ExecEnv::GetInstance()->brpc_internal_client_cache()->exist(endpoint)) {
1910
0
                    response->mutable_status()->add_error_msgs(endpoint + ": not found.");
1911
0
                    continue;
1912
0
                }
1913
1914
0
                if (ExecEnv::GetInstance()->brpc_internal_client_cache()->erase(endpoint)) {
1915
0
                    response->add_channels(endpoint);
1916
0
                } else {
1917
0
                    response->mutable_status()->add_error_msgs(endpoint + ": reset failed.");
1918
0
                }
1919
0
            }
1920
0
            if (request->endpoints_size() != response->channels_size()) {
1921
0
                response->mutable_status()->set_status_code(1);
1922
0
            }
1923
0
        }
1924
0
    });
1925
0
    if (!ret) {
1926
0
        offer_failed(response, done, _light_work_pool);
1927
0
        return;
1928
0
    }
1929
0
}
1930
1931
void PInternalService::hand_shake(google::protobuf::RpcController* controller,
1932
                                  const PHandShakeRequest* request, PHandShakeResponse* response,
1933
2.24k
                                  google::protobuf::Closure* done) {
1934
    // The light pool may be full. Handshake is used to check the connection state of brpc.
1935
    // Should not be interfered by the thread pool logic.
1936
2.24k
    brpc::ClosureGuard closure_guard(done);
1937
2.24k
    if (request->has_hello()) {
1938
2.24k
        response->set_hello(request->hello());
1939
2.24k
    }
1940
2.24k
    response->mutable_status()->set_status_code(0);
1941
2.24k
}
1942
1943
void PInternalServiceImpl::request_slave_tablet_pull_rowset(
1944
        google::protobuf::RpcController* controller, const PTabletWriteSlaveRequest* request,
1945
0
        PTabletWriteSlaveResult* response, google::protobuf::Closure* done) {
1946
0
    brpc::ClosureGuard closure_guard(done);
1947
0
    Status::NotSupported("single replica load has been removed")
1948
0
            .to_protobuf(response->mutable_status());
1949
0
}
1950
1951
void PInternalServiceImpl::response_slave_tablet_pull_rowset(
1952
        google::protobuf::RpcController* controller, const PTabletWriteSlaveDoneRequest* request,
1953
0
        PTabletWriteSlaveDoneResult* response, google::protobuf::Closure* done) {
1954
0
    brpc::ClosureGuard closure_guard(done);
1955
0
    Status::NotSupported("single replica load has been removed")
1956
0
            .to_protobuf(response->mutable_status());
1957
0
}
1958
1959
void PInternalService::multiget_data(google::protobuf::RpcController* controller,
1960
                                     const PMultiGetRequest* request, PMultiGetResponse* response,
1961
0
                                     google::protobuf::Closure* done) {
1962
0
    brpc::ClosureGuard closure_guard(done);
1963
0
#pragma GCC diagnostic push
1964
0
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1965
    // The deprecated response field is retained only to reject legacy callers explicitly.
1966
0
    Status::NotSupported("multiget_data is deprecated; use multiget_data_v2")
1967
0
            .to_protobuf(response->mutable_status());
1968
0
#pragma GCC diagnostic pop
1969
0
}
1970
1971
void PInternalService::multiget_data_v2(google::protobuf::RpcController* controller,
1972
                                        const PMultiGetRequestV2* request,
1973
                                        PMultiGetResponseV2* response,
1974
1.16k
                                        google::protobuf::Closure* done) {
1975
1.16k
    std::vector<uint64_t> id_set;
1976
1.16k
    id_set.push_back(request->wg_id());
1977
1.16k
    auto wg = ExecEnv::GetInstance()->workload_group_mgr()->get_group(id_set);
1978
1.16k
    Status st = Status::OK();
1979
1980
1.16k
    if (!wg) [[unlikely]] {
1981
0
        brpc::ClosureGuard closure_guard(done);
1982
0
        st = Status::Error<TStatusCode::CANCELLED>("fail to find wg: wg id:" +
1983
0
                                                   std::to_string(request->wg_id()));
1984
0
        st.to_protobuf(response->mutable_status());
1985
0
        return;
1986
0
    }
1987
1988
1.16k
    doris::TaskScheduler* exec_sched = nullptr;
1989
1.16k
    ScannerScheduler* scan_sched = nullptr;
1990
1.16k
    ScannerScheduler* remote_scan_sched = nullptr;
1991
1.16k
    wg->get_query_scheduler(&exec_sched, &scan_sched, &remote_scan_sched);
1992
1.16k
    DCHECK(remote_scan_sched);
1993
1994
1.16k
    st = remote_scan_sched->submit_scan_task(
1995
1.16k
            SimplifiedScanTask(
1996
1.16k
                    [request, response, done]() {
1997
1.16k
                        SCOPED_ATTACH_TASK(ExecEnv::GetInstance()->rowid_storage_reader_tracker());
1998
1.16k
                        signal::set_signal_task_id(request->query_id());
1999
                        // multi get data by rowid
2000
1.16k
                        MonotonicStopWatch watch;
2001
1.16k
                        watch.start();
2002
1.16k
                        brpc::ClosureGuard closure_guard(done);
2003
1.16k
                        RowIdStorageReader::read_by_rowids_for_rpc(*request, response);
2004
1.16k
                        LOG(INFO) << "multiget_data finished, cost(us):"
2005
1.16k
                                  << watch.elapsed_time() / 1000;
2006
1.16k
                        return true;
2007
1.16k
                    },
2008
1.16k
                    nullptr, nullptr),
2009
1.16k
            fmt::format("{}-multiget_data_v2", print_id(request->query_id())));
2010
2011
1.16k
    if (!st.ok()) {
2012
0
        brpc::ClosureGuard closure_guard(done);
2013
0
        st.to_protobuf(response->mutable_status());
2014
0
    }
2015
1.16k
}
2016
2017
void PInternalServiceImpl::get_tablet_rowset_versions(google::protobuf::RpcController* cntl_base,
2018
                                                      const PGetTabletVersionsRequest* request,
2019
                                                      PGetTabletVersionsResponse* response,
2020
0
                                                      google::protobuf::Closure* done) {
2021
0
    brpc::ClosureGuard closure_guard(done);
2022
0
    VLOG_DEBUG << "receive get tablet versions request: " << request->DebugString();
2023
0
    _engine.get_tablet_rowset_versions(request, response);
2024
0
}
2025
2026
void PInternalService::glob(google::protobuf::RpcController* controller,
2027
                            const PGlobRequest* request, PGlobResponse* response,
2028
0
                            google::protobuf::Closure* done) {
2029
0
    bool ret = _heavy_work_pool.try_offer([request, response, done]() {
2030
0
        brpc::ClosureGuard closure_guard(done);
2031
0
        std::vector<io::FileInfo> files;
2032
0
        Status st = io::global_local_filesystem()->safe_glob(request->pattern(), &files);
2033
0
        if (st.ok()) {
2034
0
            for (auto& file : files) {
2035
0
                PGlobResponse_PFileInfo* pfile = response->add_files();
2036
0
                pfile->set_file(file.file_name);
2037
0
                pfile->set_size(file.file_size);
2038
0
            }
2039
0
        }
2040
0
        st.to_protobuf(response->mutable_status());
2041
0
    });
2042
0
    if (!ret) {
2043
0
        offer_failed(response, done, _heavy_work_pool);
2044
0
        return;
2045
0
    }
2046
0
}
2047
2048
void PInternalService::group_commit_insert(google::protobuf::RpcController* controller,
2049
                                           const PGroupCommitInsertRequest* request,
2050
                                           PGroupCommitInsertResponse* response,
2051
29
                                           google::protobuf::Closure* done) {
2052
29
    TUniqueId load_id;
2053
29
    load_id.__set_hi(request->load_id().hi());
2054
29
    load_id.__set_lo(request->load_id().lo());
2055
29
    std::shared_ptr<std::mutex> lock = std::make_shared<std::mutex>();
2056
29
    std::shared_ptr<bool> is_done = std::make_shared<bool>(false);
2057
29
    bool ret = _heavy_work_pool.try_offer([this, request, response, done, load_id, lock,
2058
29
                                           is_done]() {
2059
29
        brpc::ClosureGuard closure_guard(done);
2060
29
        std::shared_ptr<StreamLoadContext> ctx = std::make_shared<StreamLoadContext>(_exec_env);
2061
29
        auto pipe = std::make_shared<io::StreamLoadPipe>(
2062
29
                io::kMaxPipeBufferedBytes /* max_buffered_bytes */, 64 * 1024 /* min_chunk_size */,
2063
29
                -1 /* total_length */, true /* use_proto */);
2064
29
        ctx->pipe = pipe;
2065
29
        Status st = _exec_env->new_load_stream_mgr()->put(load_id, ctx);
2066
29
        if (st.ok()) {
2067
29
            try {
2068
29
                st = _exec_plan_fragment_impl(
2069
29
                        request->exec_plan_fragment_request().request(),
2070
29
                        request->exec_plan_fragment_request().version(),
2071
29
                        request->exec_plan_fragment_request().compact(),
2072
29
                        [&, response, done, load_id, lock, is_done](RuntimeState* state,
2073
29
                                                                    Status* status) {
2074
29
                            std::lock_guard<std::mutex> lock1(*lock);
2075
29
                            if (*is_done) {
2076
0
                                return;
2077
0
                            }
2078
29
                            *is_done = true;
2079
29
                            brpc::ClosureGuard cb_closure_guard(done);
2080
29
                            response->set_label(state->import_label());
2081
29
                            response->set_txn_id(state->wal_id());
2082
29
                            response->set_loaded_rows(state->num_rows_load_success());
2083
29
                            response->set_filtered_rows(state->num_rows_load_filtered());
2084
29
                            status->to_protobuf(response->mutable_status());
2085
29
                            if (!state->get_error_log_file_path().empty()) {
2086
0
                                response->set_error_url(
2087
0
                                        to_load_error_http_path(state->get_error_log_file_path()));
2088
0
                            }
2089
29
                            if (!state->get_first_error_msg().empty()) {
2090
0
                                response->set_first_error_msg(state->get_first_error_msg());
2091
0
                            }
2092
29
                            _exec_env->new_load_stream_mgr()->remove(load_id);
2093
29
                        });
2094
29
            } catch (const Exception& e) {
2095
0
                st = e.to_status();
2096
0
            } catch (const std::exception& e) {
2097
0
                st = Status::Error(ErrorCode::INTERNAL_ERROR, e.what());
2098
0
            } catch (...) {
2099
0
                st = Status::Error(ErrorCode::INTERNAL_ERROR,
2100
0
                                   "_exec_plan_fragment_impl meet unknown error");
2101
0
            }
2102
29
            if (!st.ok()) {
2103
0
                LOG(WARNING) << "exec plan fragment failed, load_id=" << print_id(load_id)
2104
0
                             << ", errmsg=" << st;
2105
0
                std::lock_guard<std::mutex> lock1(*lock);
2106
0
                if (*is_done) {
2107
0
                    closure_guard.release();
2108
0
                } else {
2109
0
                    *is_done = true;
2110
0
                    st.to_protobuf(response->mutable_status());
2111
0
                    _exec_env->new_load_stream_mgr()->remove(load_id);
2112
0
                }
2113
29
            } else {
2114
29
                closure_guard.release();
2115
66
                for (int i = 0; i < request->data().size(); ++i) {
2116
37
                    std::unique_ptr<PDataRow> row(new PDataRow());
2117
37
                    row->CopyFrom(request->data(i));
2118
37
                    st = pipe->append(std::move(row));
2119
37
                    if (!st.ok()) {
2120
0
                        break;
2121
0
                    }
2122
37
                }
2123
29
                if (st.ok()) {
2124
29
                    static_cast<void>(pipe->finish());
2125
29
                }
2126
29
            }
2127
29
        }
2128
29
    });
2129
29
    if (!ret) {
2130
0
        _exec_env->new_load_stream_mgr()->remove(load_id);
2131
0
        offer_failed(response, done, _heavy_work_pool);
2132
0
        return;
2133
0
    }
2134
29
};
2135
2136
void PInternalService::get_wal_queue_size(google::protobuf::RpcController* controller,
2137
                                          const PGetWalQueueSizeRequest* request,
2138
                                          PGetWalQueueSizeResponse* response,
2139
1.18k
                                          google::protobuf::Closure* done) {
2140
1.18k
    bool ret = _heavy_work_pool.try_offer([this, request, response, done]() {
2141
1.18k
        brpc::ClosureGuard closure_guard(done);
2142
1.18k
        Status st = Status::OK();
2143
1.18k
        auto table_id = request->table_id();
2144
1.18k
        auto count = _exec_env->wal_mgr()->get_wal_queue_size(table_id);
2145
1.18k
        response->set_size(count);
2146
1.18k
        response->mutable_status()->set_status_code(st.code());
2147
1.18k
    });
2148
1.18k
    if (!ret) {
2149
0
        offer_failed(response, done, _heavy_work_pool);
2150
0
    }
2151
1.18k
}
2152
2153
void PInternalService::get_be_resource(google::protobuf::RpcController* controller,
2154
                                       const PGetBeResourceRequest* request,
2155
                                       PGetBeResourceResponse* response,
2156
0
                                       google::protobuf::Closure* done) {
2157
0
    bool ret = _heavy_work_pool.try_offer([response, done]() {
2158
0
        brpc::ClosureGuard closure_guard(done);
2159
0
        int64_t mem_limit = MemInfo::mem_limit();
2160
0
        int64_t mem_usage = PerfCounters::get_vm_rss();
2161
2162
0
        PGlobalResourceUsage* global_resource_usage = response->mutable_global_be_resource_usage();
2163
0
        global_resource_usage->set_mem_limit(mem_limit);
2164
0
        global_resource_usage->set_mem_usage(mem_usage);
2165
2166
0
        Status st = Status::OK();
2167
0
        response->mutable_status()->set_status_code(st.code());
2168
0
    });
2169
0
    if (!ret) {
2170
0
        offer_failed(response, done, _heavy_work_pool);
2171
0
    }
2172
0
}
2173
2174
void PInternalService::delete_dictionary(google::protobuf::RpcController* controller,
2175
                                         const PDeleteDictionaryRequest* request,
2176
                                         PDeleteDictionaryResponse* response,
2177
3
                                         google::protobuf::Closure* done) {
2178
3
    brpc::ClosureGuard closure_guard(done);
2179
3
    Status st = ExecEnv::GetInstance()->dict_factory()->delete_dict(request->dictionary_id());
2180
3
    st.to_protobuf(response->mutable_status());
2181
3
}
2182
2183
void PInternalService::commit_refresh_dictionary(google::protobuf::RpcController* controller,
2184
                                                 const PCommitRefreshDictionaryRequest* request,
2185
                                                 PCommitRefreshDictionaryResponse* response,
2186
89
                                                 google::protobuf::Closure* done) {
2187
89
    brpc::ClosureGuard closure_guard(done);
2188
89
    Status st = ExecEnv::GetInstance()->dict_factory()->commit_refresh_dict(
2189
89
            request->dictionary_id(), request->version_id());
2190
89
    st.to_protobuf(response->mutable_status());
2191
89
}
2192
2193
void PInternalService::abort_refresh_dictionary(google::protobuf::RpcController* controller,
2194
                                                const PAbortRefreshDictionaryRequest* request,
2195
                                                PAbortRefreshDictionaryResponse* response,
2196
2
                                                google::protobuf::Closure* done) {
2197
2
    brpc::ClosureGuard closure_guard(done);
2198
2
    Status st = ExecEnv::GetInstance()->dict_factory()->abort_refresh_dict(request->dictionary_id(),
2199
2
                                                                           request->version_id());
2200
2
    st.to_protobuf(response->mutable_status());
2201
2
}
2202
2203
void PInternalService::get_tablet_rowsets(google::protobuf::RpcController* controller,
2204
                                          const PGetTabletRowsetsRequest* request,
2205
                                          PGetTabletRowsetsResponse* response,
2206
0
                                          google::protobuf::Closure* done) {
2207
0
    DCHECK(config::is_cloud_mode());
2208
0
    auto start_time = GetMonoTimeMicros();
2209
0
    Defer defer {
2210
0
            [&]() { g_process_remote_fetch_rowsets_latency << GetMonoTimeMicros() - start_time; }};
2211
0
    brpc::ClosureGuard closure_guard(done);
2212
0
    LOG(INFO) << "process get tablet rowsets, request=" << request->ShortDebugString();
2213
0
    if (!request->has_tablet_id() || !request->has_version_start() || !request->has_version_end()) {
2214
0
        Status::InvalidArgument("missing params tablet/version_start/version_end")
2215
0
                .to_protobuf(response->mutable_status());
2216
0
        return;
2217
0
    }
2218
0
    CloudStorageEngine& storage = ExecEnv::GetInstance()->storage_engine().to_cloud();
2219
2220
0
    auto maybe_tablet =
2221
0
            storage.tablet_mgr().get_tablet(request->tablet_id(), /*warmup data*/ false,
2222
0
                                            /*syn_delete_bitmap*/ false, /*delete_bitmap*/ nullptr,
2223
0
                                            /*local_only*/ true);
2224
0
    if (!maybe_tablet) {
2225
0
        maybe_tablet.error().to_protobuf(response->mutable_status());
2226
0
        return;
2227
0
    }
2228
0
    auto tablet = maybe_tablet.value();
2229
0
    Result<CaptureRowsetResult> ret;
2230
0
    {
2231
0
        std::shared_lock l(tablet->get_header_lock());
2232
0
        ret = tablet->capture_consistent_rowsets_unlocked(
2233
0
                {request->version_start(), request->version_end()},
2234
0
                CaptureRowsetOps {.enable_fetch_rowsets_from_peers = false});
2235
0
    }
2236
0
    if (!ret) {
2237
0
        ret.error().to_protobuf(response->mutable_status());
2238
0
        return;
2239
0
    }
2240
0
    auto rowsets = std::move(ret.value().rowsets);
2241
0
    for (const auto& rs : rowsets) {
2242
0
        RowsetMetaPB meta;
2243
0
        rs->rowset_meta()->to_rowset_pb(&meta);
2244
0
        response->mutable_rowsets()->Add(std::move(meta));
2245
0
    }
2246
0
    if (request->has_delete_bitmap_keys()) {
2247
0
        DCHECK(tablet->need_read_delete_bitmap());
2248
0
        auto delete_bitmap = std::move(ret.value().delete_bitmap);
2249
0
        auto keys_pb = request->delete_bitmap_keys();
2250
0
        size_t len = keys_pb.rowset_ids().size();
2251
0
        DCHECK_EQ(len, keys_pb.segment_ids().size());
2252
0
        DCHECK_EQ(len, keys_pb.versions().size());
2253
0
        std::set<DeleteBitmap::BitmapKey> keys;
2254
0
        for (size_t i = 0; i < len; ++i) {
2255
0
            RowsetId rs_id;
2256
0
            rs_id.init(keys_pb.rowset_ids(i));
2257
0
            keys.emplace(rs_id, keys_pb.segment_ids(i), keys_pb.versions(i));
2258
0
        }
2259
0
        auto diffset = delete_bitmap->diffset(keys).to_pb();
2260
0
        *response->mutable_delete_bitmap() = std::move(diffset);
2261
0
    }
2262
0
    Status::OK().to_protobuf(response->mutable_status());
2263
0
}
2264
2265
void PInternalService::request_cdc_client(google::protobuf::RpcController* controller,
2266
                                          const PRequestCdcClientRequest* request,
2267
                                          PRequestCdcClientResult* result,
2268
0
                                          google::protobuf::Closure* done) {
2269
0
    bool ret = _heavy_work_pool.try_offer([this, request, result, done]() {
2270
0
        _exec_env->cdc_client_mgr()->request_cdc_client_impl(request, result, done);
2271
0
    });
2272
2273
0
    if (!ret) {
2274
0
        offer_failed(result, done, _heavy_work_pool);
2275
0
        return;
2276
0
    }
2277
0
}
2278
2279
void PInternalService::sync_tablet_meta(google::protobuf::RpcController* controller,
2280
                                        const PSyncTabletMetaRequest* request,
2281
                                        PSyncTabletMetaResponse* response,
2282
0
                                        google::protobuf::Closure* done) {
2283
0
    brpc::ClosureGuard closure_guard(done);
2284
0
    Status::NotSupported("sync_tablet_meta only supports cloud mode")
2285
0
            .to_protobuf(response->mutable_status());
2286
0
}
2287
2288
#include "common/compile_check_avoid_end.h"
2289
} // namespace doris