Coverage Report

Created: 2026-10-16 14:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/util/proto_util.h
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#pragma once
19
20
#include <brpc/http_method.h>
21
#include <gen_cpp/internal_service.pb.h>
22
23
#include <memory>
24
#include <string>
25
#include <vector>
26
27
#include "common/config.h"
28
#include "common/status.h"
29
#include "runtime/exec_env.h"
30
#include "runtime/runtime_state.h"
31
#include "util/brpc_client_cache.h"
32
#include "util/debug_points.h"
33
#include "util/defer_op.h"
34
#include "util/network_util.h"
35
36
namespace doris {
37
38
// When the tuple/block data is greater than 2G, embed the tuple/block data
39
// and the request serialization string in the attachment, and use "http" brpc.
40
// "http"brpc requires that only one of request and attachment be non-null.
41
//
42
// 2G: In the default "baidu_std" brpcd, upper limit of the request and attachment length is 2G.
43
constexpr size_t MIN_HTTP_BRPC_SIZE = (1ULL << 31);
44
45
// Attachment layout shared by every http send path:
46
//
47
//   [int64 request_size][serialized request][int64 payload_size][payload]...
48
//
49
// The serialized request carries everything but the block payloads (PBlock::column_values).
50
// One payload section follows per payload block of the request, in block order, see
51
// payload_blocks(). A request with a single block therefore keeps the layout older
52
// receivers expect; receivers older than this layout read exactly one payload into the
53
// singular `block`, so a multi-payload attachment (repeated `blocks`) is only understood by
54
// receivers that carry it. Such requests could not be sent at all before (plain brpc rejected
55
// them for exceeding its size limit), so no working mixed-version case is lost.
56
57
// The blocks whose column_values travel as attachment payloads. A generic request carries one
58
// block; PTransmitDataParams carries either the singular `block` or the repeated `blocks`.
59
template <typename Params>
60
1
std::vector<PBlock*> payload_blocks(Params* brpc_request) {
61
1
    return {brpc_request->mutable_block()};
62
1
}
63
64
11
inline std::vector<PBlock*> payload_blocks(PTransmitDataParams* brpc_request) {
65
11
    if (brpc_request->has_block()) {
66
9
        DCHECK(brpc_request->blocks().empty());
67
9
        return {brpc_request->mutable_block()};
68
9
    }
69
2
    std::vector<PBlock*> blocks;
70
2
    blocks.reserve(brpc_request->blocks_size());
71
4
    for (auto& block : *brpc_request->mutable_blocks()) {
72
4
        blocks.push_back(&block);
73
4
    }
74
2
    return blocks;
75
11
}
76
77
// Append one `[int64 size][bytes]` section to the attachment.
78
15
inline Status attachment_append_section(butil::IOBuf* attachment, const std::string& data) {
79
15
    int64_t data_size = data.size();
80
15
    attachment->append(&data_size, sizeof(data_size));
81
15
    try {
82
15
        attachment->append(data);
83
15
    } catch (...) {
84
0
        LOG(WARNING) << "Try to alloc " << data_size
85
0
                     << " bytes for append data to attachment failed. ";
86
0
        return Status::MemoryAllocFailed("request embed attachment failed to memcpy {} bytes",
87
0
                                         data_size);
88
0
    }
89
15
    return Status::OK();
90
15
}
91
92
// Embed `brpc_request` followed by `payloads`, one section each, in the controller attachment.
93
template <typename Params, typename Closure>
94
Status request_embed_attachmentv2(Params* brpc_request,
95
                                  const std::vector<const std::string*>& payloads,
96
7
                                  std::unique_ptr<Closure>& closure) {
97
7
    std::string req_str;
98
7
    if (!brpc_request->SerializeToString(&req_str)) {
99
0
        return Status::InternalError("failed to serialize the request");
100
0
    }
101
7
    butil::IOBuf attachment;
102
7
    RETURN_IF_ERROR(attachment_append_section(&attachment, req_str));
103
8
    for (const auto* payload : payloads) {
104
8
        RETURN_IF_ERROR(attachment_append_section(&attachment, *payload));
105
8
    }
106
7
    closure->cntl_->request_attachment().swap(attachment);
107
7
    return Status::OK();
108
7
}
exchange_sink_buffer_test.cpp:_ZN5doris26request_embed_attachmentv2INS_19PTransmitDataParamsENS_12_GLOBAL__N_129ExchangeSinkBufferTestClosureEEENS_6StatusEPT_RKSt6vectorIPKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaISF_EERSt10unique_ptrIT0_St14default_deleteISL_EE
Line
Count
Source
96
1
                                  std::unique_ptr<Closure>& closure) {
97
1
    std::string req_str;
98
1
    if (!brpc_request->SerializeToString(&req_str)) {
99
0
        return Status::InternalError("failed to serialize the request");
100
0
    }
101
1
    butil::IOBuf attachment;
102
1
    RETURN_IF_ERROR(attachment_append_section(&attachment, req_str));
103
1
    for (const auto* payload : payloads) {
104
1
        RETURN_IF_ERROR(attachment_append_section(&attachment, *payload));
105
1
    }
106
1
    closure->cntl_->request_attachment().swap(attachment);
107
1
    return Status::OK();
108
1
}
proto_util_test.cpp:_ZN5doris26request_embed_attachmentv2INS_19PTransmitDataParamsENS_12_GLOBAL__N_120ProtoUtilTestClosureEEENS_6StatusEPT_RKSt6vectorIPKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaISF_EERSt10unique_ptrIT0_St14default_deleteISL_EE
Line
Count
Source
96
5
                                  std::unique_ptr<Closure>& closure) {
97
5
    std::string req_str;
98
5
    if (!brpc_request->SerializeToString(&req_str)) {
99
0
        return Status::InternalError("failed to serialize the request");
100
0
    }
101
5
    butil::IOBuf attachment;
102
5
    RETURN_IF_ERROR(attachment_append_section(&attachment, req_str));
103
6
    for (const auto* payload : payloads) {
104
6
        RETURN_IF_ERROR(attachment_append_section(&attachment, *payload));
105
6
    }
106
5
    closure->cntl_->request_attachment().swap(attachment);
107
5
    return Status::OK();
108
5
}
proto_util_test.cpp:_ZN5doris26request_embed_attachmentv2INS_28PTabletWriterAddBlockRequestENS_12_GLOBAL__N_120ProtoUtilTestClosureEEENS_6StatusEPT_RKSt6vectorIPKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaISF_EERSt10unique_ptrIT0_St14default_deleteISL_EE
Line
Count
Source
96
1
                                  std::unique_ptr<Closure>& closure) {
97
1
    std::string req_str;
98
1
    if (!brpc_request->SerializeToString(&req_str)) {
99
0
        return Status::InternalError("failed to serialize the request");
100
0
    }
101
1
    butil::IOBuf attachment;
102
1
    RETURN_IF_ERROR(attachment_append_section(&attachment, req_str));
103
1
    for (const auto* payload : payloads) {
104
1
        RETURN_IF_ERROR(attachment_append_section(&attachment, *payload));
105
1
    }
106
1
    closure->cntl_->request_attachment().swap(attachment);
107
1
    return Status::OK();
108
1
}
Unexecuted instantiation: _ZN5doris26request_embed_attachmentv2INS_28PTabletWriterAddBlockRequestENS_18AutoReleaseClosureIS1_NS_18WriteBlockCallbackINS_27PTabletWriterAddBlockResultEEEEEEENS_6StatusEPT_RKSt6vectorIPKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaISI_EERSt10unique_ptrIT0_St14default_deleteISO_EE
Unexecuted instantiation: _ZN5doris26request_embed_attachmentv2INS_19PTransmitDataParamsENS_18AutoReleaseClosureIS1_NS_20ExchangeSendCallbackINS_19PTransmitDataResultEEEEEEENS_6StatusEPT_RKSt6vectorIPKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaISI_EERSt10unique_ptrIT0_St14default_deleteISO_EE
109
110
template <typename Params, typename Closure>
111
Status request_embed_attachmentv2(Params* brpc_request, const std::string& data,
112
4
                                  std::unique_ptr<Closure>& closure) {
113
4
    return request_embed_attachmentv2(brpc_request, std::vector<const std::string*> {&data},
114
4
                                      closure);
115
4
}
proto_util_test.cpp:_ZN5doris26request_embed_attachmentv2INS_19PTransmitDataParamsENS_12_GLOBAL__N_120ProtoUtilTestClosureEEENS_6StatusEPT_RKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERSt10unique_ptrIT0_St14default_deleteISG_EE
Line
Count
Source
112
3
                                  std::unique_ptr<Closure>& closure) {
113
3
    return request_embed_attachmentv2(brpc_request, std::vector<const std::string*> {&data},
114
3
                                      closure);
115
3
}
proto_util_test.cpp:_ZN5doris26request_embed_attachmentv2INS_28PTabletWriterAddBlockRequestENS_12_GLOBAL__N_120ProtoUtilTestClosureEEENS_6StatusEPT_RKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERSt10unique_ptrIT0_St14default_deleteISG_EE
Line
Count
Source
112
1
                                  std::unique_ptr<Closure>& closure) {
113
1
    return request_embed_attachmentv2(brpc_request, std::vector<const std::string*> {&data},
114
1
                                      closure);
115
1
}
Unexecuted instantiation: _ZN5doris26request_embed_attachmentv2INS_28PTabletWriterAddBlockRequestENS_18AutoReleaseClosureIS1_NS_18WriteBlockCallbackINS_27PTabletWriterAddBlockResultEEEEEEENS_6StatusEPT_RKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERSt10unique_ptrIT0_St14default_deleteISJ_EE
116
117
// Embed a request that owns its block: column_values is moved into the attachment and the
118
// request keeps the field present but empty.
119
template <typename Params, typename Closure>
120
Status request_embed_attachment_contain_blockv2(Params* brpc_request,
121
3
                                                std::unique_ptr<Closure>& closure) {
122
3
    auto* block = brpc_request->mutable_block();
123
3
    std::string column_values = std::move(*block->mutable_column_values());
124
3
    block->mutable_column_values()->clear();
125
3
    return request_embed_attachmentv2(brpc_request, column_values, closure);
126
3
}
proto_util_test.cpp:_ZN5doris40request_embed_attachment_contain_blockv2INS_19PTransmitDataParamsENS_12_GLOBAL__N_120ProtoUtilTestClosureEEENS_6StatusEPT_RSt10unique_ptrIT0_St14default_deleteIS8_EE
Line
Count
Source
121
2
                                                std::unique_ptr<Closure>& closure) {
122
2
    auto* block = brpc_request->mutable_block();
123
2
    std::string column_values = std::move(*block->mutable_column_values());
124
2
    block->mutable_column_values()->clear();
125
2
    return request_embed_attachmentv2(brpc_request, column_values, closure);
126
2
}
proto_util_test.cpp:_ZN5doris40request_embed_attachment_contain_blockv2INS_28PTabletWriterAddBlockRequestENS_12_GLOBAL__N_120ProtoUtilTestClosureEEENS_6StatusEPT_RSt10unique_ptrIT0_St14default_deleteIS8_EE
Line
Count
Source
121
1
                                                std::unique_ptr<Closure>& closure) {
122
1
    auto* block = brpc_request->mutable_block();
123
1
    std::string column_values = std::move(*block->mutable_column_values());
124
1
    block->mutable_column_values()->clear();
125
1
    return request_embed_attachmentv2(brpc_request, column_values, closure);
126
1
}
Unexecuted instantiation: _ZN5doris40request_embed_attachment_contain_blockv2INS_28PTabletWriterAddBlockRequestENS_18AutoReleaseClosureIS1_NS_18WriteBlockCallbackINS_27PTabletWriterAddBlockResultEEEEEEENS_6StatusEPT_RSt10unique_ptrIT0_St14default_deleteISB_EE
127
128
// Embed a request whose blocks only borrow their column_values (see
129
// ExchangeSinkBuffer / borrow_block()). Each payload is detached from the request while the
130
// request is serialized, appended by reference and attached back, so the owner of the payload
131
// is never read through the request's presence bits nor mutated: the same owner may be
132
// serialized by other channels at the same time.
133
template <typename Closure>
134
Status request_embed_attachment_borrowed_blocksv2(PTransmitDataParams* brpc_request,
135
3
                                                  std::unique_ptr<Closure>& closure) {
136
3
    std::vector<PBlock*> blocks = payload_blocks(brpc_request);
137
3
    std::vector<std::string*> payloads;
138
3
    payloads.reserve(blocks.size());
139
    // Registered before any payload is detached: if a placeholder allocation below throws, the
140
    // payloads detached so far are attached back and the placeholders already installed are freed
141
    // by set_allocated_column_values().
142
3
    Defer attach_back([&]() {
143
7
        for (size_t i = 0; i < payloads.size(); ++i) {
144
4
            blocks[i]->set_allocated_column_values(payloads[i]);
145
4
        }
146
3
    });
exchange_sink_buffer_test.cpp:_ZZN5doris42request_embed_attachment_borrowed_blocksv2INS_12_GLOBAL__N_129ExchangeSinkBufferTestClosureEEENS_6StatusEPNS_19PTransmitDataParamsERSt10unique_ptrIT_St14default_deleteIS7_EEENKUlvE_clEv
Line
Count
Source
142
1
    Defer attach_back([&]() {
143
2
        for (size_t i = 0; i < payloads.size(); ++i) {
144
1
            blocks[i]->set_allocated_column_values(payloads[i]);
145
1
        }
146
1
    });
proto_util_test.cpp:_ZZN5doris42request_embed_attachment_borrowed_blocksv2INS_12_GLOBAL__N_120ProtoUtilTestClosureEEENS_6StatusEPNS_19PTransmitDataParamsERSt10unique_ptrIT_St14default_deleteIS7_EEENKUlvE_clEv
Line
Count
Source
142
2
    Defer attach_back([&]() {
143
5
        for (size_t i = 0; i < payloads.size(); ++i) {
144
3
            blocks[i]->set_allocated_column_values(payloads[i]);
145
3
        }
146
2
    });
Unexecuted instantiation: _ZZN5doris42request_embed_attachment_borrowed_blocksv2INS_18AutoReleaseClosureINS_19PTransmitDataParamsENS_20ExchangeSendCallbackINS_19PTransmitDataResultEEEEEEENS_6StatusEPS2_RSt10unique_ptrIT_St14default_deleteISA_EEENKUlvE_clEv
147
4
    for (auto* block : blocks) {
148
4
        payloads.push_back(block->release_column_values());
149
4
        DCHECK(payloads.back() != nullptr);
150
        // Keep the field present on the wire: receivers that take the payload slot before
151
        // parsing the request rely on the serialized field to restore its presence bit.
152
4
        block->set_column_values("");
153
4
    }
154
3
    return request_embed_attachmentv2(
155
3
            brpc_request, std::vector<const std::string*>(payloads.begin(), payloads.end()),
156
3
            closure);
157
3
}
exchange_sink_buffer_test.cpp:_ZN5doris42request_embed_attachment_borrowed_blocksv2INS_12_GLOBAL__N_129ExchangeSinkBufferTestClosureEEENS_6StatusEPNS_19PTransmitDataParamsERSt10unique_ptrIT_St14default_deleteIS7_EE
Line
Count
Source
135
1
                                                  std::unique_ptr<Closure>& closure) {
136
1
    std::vector<PBlock*> blocks = payload_blocks(brpc_request);
137
1
    std::vector<std::string*> payloads;
138
1
    payloads.reserve(blocks.size());
139
    // Registered before any payload is detached: if a placeholder allocation below throws, the
140
    // payloads detached so far are attached back and the placeholders already installed are freed
141
    // by set_allocated_column_values().
142
1
    Defer attach_back([&]() {
143
1
        for (size_t i = 0; i < payloads.size(); ++i) {
144
1
            blocks[i]->set_allocated_column_values(payloads[i]);
145
1
        }
146
1
    });
147
1
    for (auto* block : blocks) {
148
1
        payloads.push_back(block->release_column_values());
149
1
        DCHECK(payloads.back() != nullptr);
150
        // Keep the field present on the wire: receivers that take the payload slot before
151
        // parsing the request rely on the serialized field to restore its presence bit.
152
1
        block->set_column_values("");
153
1
    }
154
1
    return request_embed_attachmentv2(
155
1
            brpc_request, std::vector<const std::string*>(payloads.begin(), payloads.end()),
156
1
            closure);
157
1
}
proto_util_test.cpp:_ZN5doris42request_embed_attachment_borrowed_blocksv2INS_12_GLOBAL__N_120ProtoUtilTestClosureEEENS_6StatusEPNS_19PTransmitDataParamsERSt10unique_ptrIT_St14default_deleteIS7_EE
Line
Count
Source
135
2
                                                  std::unique_ptr<Closure>& closure) {
136
2
    std::vector<PBlock*> blocks = payload_blocks(brpc_request);
137
2
    std::vector<std::string*> payloads;
138
2
    payloads.reserve(blocks.size());
139
    // Registered before any payload is detached: if a placeholder allocation below throws, the
140
    // payloads detached so far are attached back and the placeholders already installed are freed
141
    // by set_allocated_column_values().
142
2
    Defer attach_back([&]() {
143
2
        for (size_t i = 0; i < payloads.size(); ++i) {
144
2
            blocks[i]->set_allocated_column_values(payloads[i]);
145
2
        }
146
2
    });
147
3
    for (auto* block : blocks) {
148
3
        payloads.push_back(block->release_column_values());
149
3
        DCHECK(payloads.back() != nullptr);
150
        // Keep the field present on the wire: receivers that take the payload slot before
151
        // parsing the request rely on the serialized field to restore its presence bit.
152
3
        block->set_column_values("");
153
3
    }
154
2
    return request_embed_attachmentv2(
155
2
            brpc_request, std::vector<const std::string*>(payloads.begin(), payloads.end()),
156
2
            closure);
157
2
}
Unexecuted instantiation: _ZN5doris42request_embed_attachment_borrowed_blocksv2INS_18AutoReleaseClosureINS_19PTransmitDataParamsENS_20ExchangeSendCallbackINS_19PTransmitDataResultEEEEEEENS_6StatusEPS2_RSt10unique_ptrIT_St14default_deleteISA_EE
158
159
35
inline bool enable_http_send_block(const PTransmitDataParams& request) {
160
35
    if (!config::transfer_large_data_by_brpc) {
161
0
        return false;
162
0
    }
163
35
    if (!request.has_block() && request.blocks().empty()) {
164
29
        return false;
165
29
    }
166
    // Force the http attachment path in tests without needing an actual >= 2G request,
167
    // so regression tests can exercise transmit_block_httpv2.
168
6
    DBUG_EXECUTE_IF("proto_util.enable_http_send_block.always_http", { return true; });
169
4
    return request.ByteSizeLong() >= MIN_HTTP_BRPC_SIZE;
170
6
}
171
172
template <typename Closure>
173
void transmit_blockv2(PBackendService_Stub* stub, std::unique_ptr<Closure> closure) {
174
    closure->cntl_->http_request().Clear();
175
    stub->transmit_block(closure->cntl_.get(), closure->request_.get(), closure->response_.get(),
176
                         closure.get());
177
    closure.release();
178
}
179
180
template <typename Closure>
181
11
void transmit_serialized_block(PBackendService_Stub* stub, std::unique_ptr<Closure> closure) {
182
    // SerializedRequest bypasses brpc's protobuf serializer, including request compression.
183
    // Exchange compresses column_values before preparing the shared protobuf fragment.
184
11
    DCHECK_EQ(closure->cntl_->request_compress_type(), brpc::COMPRESS_TYPE_NONE);
185
11
    static const auto* method = PBackendService::descriptor()->FindMethodByName("transmit_block");
186
11
    closure->cntl_->http_request().Clear();
187
11
    stub->channel()->CallMethod(method, closure->cntl_.get(), closure->request_.get(),
188
11
                                closure->response_.get(), closure.get());
189
11
    closure.release();
190
11
}
191
192
template <typename Closure>
193
Status transmit_block_httpv2(ExecEnv* exec_env, std::unique_ptr<Closure> closure,
194
0
                             TNetworkAddress brpc_dest_addr) {
195
0
    RETURN_IF_ERROR(request_embed_attachment_borrowed_blocksv2(closure->request_.get(), closure));
196
197
0
    std::string host = brpc_dest_addr.hostname;
198
0
    auto* dns_cache = ExecEnv::GetInstance()->dns_cache();
199
0
    if (dns_cache == nullptr) {
200
0
        LOG(WARNING) << "DNS cache is not initialized, skipping hostname resolve";
201
0
    } else if (!is_valid_ip(brpc_dest_addr.hostname)) {
202
0
        Status status = dns_cache->get(brpc_dest_addr.hostname, &host);
203
0
        if (!status.ok()) {
204
0
            LOG(WARNING) << "failed to get ip from host " << brpc_dest_addr.hostname << ": "
205
0
                         << status.to_string();
206
0
            return Status::InternalError("failed to get ip from host {}", brpc_dest_addr.hostname);
207
0
        }
208
0
    }
209
    //format an ipv6 address
210
0
    std::string brpc_url = get_brpc_http_url(brpc_dest_addr.hostname, brpc_dest_addr.port);
211
212
0
    std::shared_ptr<PBackendService_Stub> brpc_http_stub =
213
0
            exec_env->brpc_internal_client_cache()->get_new_client_no_cache(brpc_url, "http");
214
0
    if (brpc_http_stub == nullptr) {
215
0
        return Status::InternalError("failed to open brpc http client to {}", brpc_url);
216
0
    }
217
0
    closure->cntl_->http_request().uri() =
218
0
            brpc_url + "/PInternalServiceImpl/transmit_block_by_http";
219
0
    closure->cntl_->http_request().set_method(brpc::HTTP_METHOD_POST);
220
0
    closure->cntl_->http_request().set_content_type("application/json");
221
0
    brpc_http_stub->transmit_block_by_http(closure->cntl_.get(), nullptr, closure->response_.get(),
222
0
                                           closure.get());
223
0
    closure.release();
224
225
0
    return Status::OK();
226
0
}
227
228
// Read the next `[int64 size][bytes]` section at `*offset` into `data`. Every size is checked
229
// against the attachment length, so a truncated or mis-framed attachment fails here instead of
230
// being accepted with a short or empty payload.
231
inline Status attachment_read_section(const butil::IOBuf& io_buf, size_t* offset,
232
21
                                      std::string* data) {
233
21
    int64_t size;
234
21
    if (io_buf.size() < *offset + sizeof(size)) {
235
2
        return Status::InternalError("attachment truncated: size prefix at offset {} exceeds {}",
236
2
                                     *offset, io_buf.size());
237
2
    }
238
19
    io_buf.copy_to(&size, sizeof(size), *offset);
239
19
    *offset += sizeof(size);
240
19
    if (size < 0 || io_buf.size() - *offset < static_cast<size_t>(size)) {
241
2
        return Status::InternalError(
242
2
                "attachment truncated: section of {} bytes at offset {} exceeds {}", size, *offset,
243
2
                io_buf.size());
244
2
    }
245
17
    try {
246
17
        io_buf.copy_to(data, size, *offset);
247
17
    } catch (...) {
248
0
        LOG(WARNING) << "Try to alloc " << size
249
0
                     << " bytes for extract data from attachment failed. ";
250
0
        return Status::MemoryAllocFailed("attachment extract request failed to memcpy {} bytes",
251
0
                                         size);
252
0
    }
253
17
    *offset += size;
254
17
    return Status::OK();
255
17
}
256
257
// Extract the brpc request and the payload of each of its blocks from the controller attachment.
258
template <typename Params>
259
11
Status attachment_extract_request_contain_block(Params* brpc_request, brpc::Controller* cntl) {
260
11
    const butil::IOBuf& io_buf = cntl->request_attachment();
261
11
    size_t offset = 0;
262
11
    std::string req_str;
263
11
    RETURN_IF_ERROR(attachment_read_section(io_buf, &offset, &req_str));
264
9
    if (!brpc_request->ParseFromString(req_str)) {
265
0
        return Status::InternalError("failed to parse the request from attachment");
266
0
    }
267
    // Take the payload slots only after parsing: ParseFromString() resets presence bits, and
268
    // mutable_column_values() marks the field present again, so a later PBlock::CopyFrom() keeps
269
    // the payload whether or not the serialized request carried the field.
270
10
    for (PBlock* block : payload_blocks(brpc_request)) {
271
10
        RETURN_IF_ERROR(attachment_read_section(io_buf, &offset, block->mutable_column_values()));
272
10
    }
273
7
    return Status::OK();
274
9
}
_ZN5doris40attachment_extract_request_contain_blockINS_19PTransmitDataParamsEEENS_6StatusEPT_PN4brpc10ControllerE
Line
Count
Source
259
10
Status attachment_extract_request_contain_block(Params* brpc_request, brpc::Controller* cntl) {
260
10
    const butil::IOBuf& io_buf = cntl->request_attachment();
261
10
    size_t offset = 0;
262
10
    std::string req_str;
263
10
    RETURN_IF_ERROR(attachment_read_section(io_buf, &offset, &req_str));
264
8
    if (!brpc_request->ParseFromString(req_str)) {
265
0
        return Status::InternalError("failed to parse the request from attachment");
266
0
    }
267
    // Take the payload slots only after parsing: ParseFromString() resets presence bits, and
268
    // mutable_column_values() marks the field present again, so a later PBlock::CopyFrom() keeps
269
    // the payload whether or not the serialized request carried the field.
270
9
    for (PBlock* block : payload_blocks(brpc_request)) {
271
9
        RETURN_IF_ERROR(attachment_read_section(io_buf, &offset, block->mutable_column_values()));
272
9
    }
273
6
    return Status::OK();
274
8
}
_ZN5doris40attachment_extract_request_contain_blockINS_28PTabletWriterAddBlockRequestEEENS_6StatusEPT_PN4brpc10ControllerE
Line
Count
Source
259
1
Status attachment_extract_request_contain_block(Params* brpc_request, brpc::Controller* cntl) {
260
1
    const butil::IOBuf& io_buf = cntl->request_attachment();
261
1
    size_t offset = 0;
262
1
    std::string req_str;
263
1
    RETURN_IF_ERROR(attachment_read_section(io_buf, &offset, &req_str));
264
1
    if (!brpc_request->ParseFromString(req_str)) {
265
0
        return Status::InternalError("failed to parse the request from attachment");
266
0
    }
267
    // Take the payload slots only after parsing: ParseFromString() resets presence bits, and
268
    // mutable_column_values() marks the field present again, so a later PBlock::CopyFrom() keeps
269
    // the payload whether or not the serialized request carried the field.
270
1
    for (PBlock* block : payload_blocks(brpc_request)) {
271
1
        RETURN_IF_ERROR(attachment_read_section(io_buf, &offset, block->mutable_column_values()));
272
1
    }
273
1
    return Status::OK();
274
1
}
275
276
} // namespace doris