Coverage Report

Created: 2026-10-26 07:18

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