Coverage Report

Created: 2026-10-23 05:44

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