Skip to content

Commit 2f02bce

Browse files
authored
Merge pull request ceph#56834 from galsalomon66/fix_error_message_flow
rgw/s3select : fix for error flow. add an option to disable s3select-request. Reviewed-by: J. Eric Ivancich <[email protected]>
2 parents f3be254 + 53ad57c commit 2f02bce

File tree

3 files changed

+54
-23
lines changed

3 files changed

+54
-23
lines changed

src/common/options/rgw.yaml.in

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ options:
5151
services:
5252
- rgw
5353
with_legacy: true
54+
- name: rgw_disable_s3select
55+
type: bool
56+
level: advanced
57+
desc: disable the s3select operation; RGW will report an error and will return ERR_INVALID_REQUEST.
58+
default: false
59+
services:
60+
- rgw
61+
with_legacy: true
5462
- name: rgw_rados_tracing
5563
type: bool
5664
level: advanced

src/rgw/rgw_s3select.cc

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ void aws_response_handler::init_success_response()
173173

174174
void aws_response_handler::send_continuation_response()
175175
{
176+
m_fp_chunk_encoding();
176177
set_continue_buffer();
177178
continue_result.resize(header_crc_size, '\0');
178179
get_buffer()->clear();
@@ -203,6 +204,7 @@ void aws_response_handler::init_stats_response()
203204

204205
void aws_response_handler::init_end_response()
205206
{
207+
m_fp_chunk_encoding();
206208
sql_result.resize(header_crc_size, '\0');
207209
get_buffer()->clear();
208210
header_size = create_header_end();
@@ -212,12 +214,13 @@ void aws_response_handler::init_end_response()
212214
rgw_flush_formatter_and_reset(s, s->formatter);
213215
}
214216

215-
void aws_response_handler::send_error_response(const char* error_message)
217+
void aws_response_handler::send_error_response(const char* error_code, const char* error_message, const char* resource_id)
216218
{
217-
//currently not in use. need to change the s3-test, this error-response raises a boto3 exception
219+
m_fp_chunk_encoding();
220+
std::string out_error_msg = std::string(error_code) + " :" + std::string(error_message) + " :" + std::string(resource_id);
218221
error_result.resize(header_crc_size, '\0');
219222
get_buffer()->clear();
220-
header_size = create_error_header_records(error_message);
223+
header_size = create_error_header_records(out_error_msg.data());
221224
error_result.append(get_buffer()->c_str(), header_size);
222225

223226
int buff_len = create_message(header_size,&error_result);
@@ -230,14 +233,17 @@ void aws_response_handler::send_success_response()
230233
#ifdef PAYLOAD_TAG
231234
sql_result.append(END_PAYLOAD_LINE);
232235
#endif
236+
m_fp_chunk_encoding();
233237
int buff_len = create_message(m_success_header_size);
234238
s->formatter->write_bin_data(sql_result.data(), buff_len);
235239
rgw_flush_formatter_and_reset(s, s->formatter);
236240
}
237241

238-
void aws_response_handler::send_error_response_rgw_formatter(const char* error_code,
239-
const char* error_message,
240-
const char* resource_id)
242+
static constexpr const char* empty_error="--";
243+
244+
void aws_response_handler::send_error_response_rgw_formatter(const char* error_code = empty_error,
245+
const char* error_message = empty_error,
246+
const char* resource_id = empty_error)
241247
{
242248
set_req_state_err(s, 0);
243249
dump_errno(s, 400);
@@ -254,6 +260,7 @@ void aws_response_handler::send_error_response_rgw_formatter(const char* error_c
254260

255261
void aws_response_handler::send_progress_response()
256262
{
263+
m_fp_chunk_encoding();
257264
std::string progress_payload = fmt::format("<?xml version=\"1.0\" encoding=\"UTF-8\"?><Progress><BytesScanned>{}</BytesScanned><BytesProcessed>{}</BytesProcessed><BytesReturned>{}</BytesReturned></Progress>"
258265
, get_processed_size(), get_processed_size(), get_total_bytes_returned());
259266
sql_result.append(progress_payload);
@@ -264,6 +271,7 @@ void aws_response_handler::send_progress_response()
264271

265272
void aws_response_handler::send_stats_response()
266273
{
274+
m_fp_chunk_encoding();
267275
std::string stats_payload = fmt::format("<?xml version=\"1.0\" encoding=\"UTF-8\"?><Stats><BytesScanned>{}</BytesScanned><BytesProcessed>{}</BytesProcessed><BytesReturned>{}</BytesReturned></Stats>"
268276
, get_processed_size(), get_processed_size(), get_total_bytes_returned());
269277
sql_result.append(stats_payload);
@@ -304,12 +312,10 @@ RGWSelectObj_ObjStore_S3::RGWSelectObj_ObjStore_S3():
304312
return 0;
305313
};
306314
fp_s3select_result_format = [this](std::string& result) {
307-
fp_chunked_transfer_encoding();
308315
m_aws_response_handler.send_success_response();
309316
return 0;
310317
};
311318
fp_s3select_continue = [this](std::string& result) {
312-
fp_chunked_transfer_encoding();
313319
m_aws_response_handler.send_continuation_response();
314320
return 0;
315321
};
@@ -330,6 +336,7 @@ RGWSelectObj_ObjStore_S3::RGWSelectObj_ObjStore_S3():
330336
}
331337
chunk_number++;
332338
};
339+
333340
}
334341

335342
RGWSelectObj_ObjStore_S3::~RGWSelectObj_ObjStore_S3()
@@ -429,7 +436,7 @@ int RGWSelectObj_ObjStore_S3::run_s3select_on_csv(const char* query, const char*
429436

430437
if (s3select_syntax.get_error_description().empty() == false) {
431438
//error-flow (syntax-error)
432-
m_aws_response_handler.send_error_response_rgw_formatter(s3select_syntax_error,s3select_syntax.get_error_description().c_str(),s3select_resource_id);
439+
m_aws_response_handler.send_error_response(s3select_syntax_error,s3select_syntax.get_error_description().c_str(),s3select_resource_id);
433440
ldpp_dout(this, 10) << "s3-select query: failed to prase the following query {" << query << "}" << dendl;
434441
ldpp_dout(this, 10) << "s3-select query: syntax-error {" << s3select_syntax.get_error_description() << "}" << dendl;
435442
return -1;
@@ -446,7 +453,7 @@ int RGWSelectObj_ObjStore_S3::run_s3select_on_csv(const char* query, const char*
446453

447454
if (status < 0) {
448455
//error flow(processing-time)
449-
m_aws_response_handler.send_error_response_rgw_formatter(s3select_processTime_error,m_s3_csv_object.get_error_description().c_str(),s3select_resource_id);
456+
m_aws_response_handler.send_error_response(s3select_processTime_error,m_s3_csv_object.get_error_description().data(),s3select_resource_id);
450457

451458
ldpp_dout(this, 10) << "s3-select query: failed to process query; {" << m_s3_csv_object.get_error_description() << "}" << dendl;
452459
return -1;
@@ -458,7 +465,6 @@ int RGWSelectObj_ObjStore_S3::run_s3select_on_csv(const char* query, const char*
458465
}
459466
ldpp_dout(this, 10) << "s3-select: complete chunk processing : chunk length = " << input_length << dendl;
460467
if (enable_progress == true) {
461-
fp_chunked_transfer_encoding();
462468
m_aws_response_handler.init_progress_response();
463469
m_aws_response_handler.send_progress_response();
464470
}
@@ -491,8 +497,7 @@ int RGWSelectObj_ObjStore_S3::run_s3select_on_parquet(const char* query)
491497
}
492498
if (s3select_syntax.get_error_description().empty() == false) {
493499
//the SQL statement failed the syntax parser
494-
fp_chunked_transfer_encoding();
495-
m_aws_response_handler.send_error_response(m_s3_parquet_object.get_error_description().c_str());
500+
m_aws_response_handler.send_error_response(s3select_syntax_error,m_s3_parquet_object.get_error_description().c_str(),s3select_resource_id);
496501

497502
ldpp_dout(this, 10) << "s3-select query: failed to prase query; {" << s3select_syntax.get_error_description() << "}" << dendl;
498503
status = -1;
@@ -502,8 +507,7 @@ int RGWSelectObj_ObjStore_S3::run_s3select_on_parquet(const char* query)
502507
status = m_s3_parquet_object.run_s3select_on_object(m_aws_response_handler.get_sql_result());
503508
if (status < 0) {
504509

505-
fp_chunked_transfer_encoding();
506-
m_aws_response_handler.send_error_response(m_s3_parquet_object.get_error_description().c_str());
510+
m_aws_response_handler.send_error_response(s3select_processTime_error,m_s3_parquet_object.get_error_description().c_str(),s3select_resource_id);
507511

508512
return -1;
509513
}
@@ -516,7 +520,7 @@ int RGWSelectObj_ObjStore_S3::run_s3select_on_json(const char* query, const char
516520
{
517521
int status = 0;
518522

519-
m_s3_csv_object.set_external_system_functions(fp_s3select_continue,
523+
m_s3_json_object.set_external_system_functions(fp_s3select_continue,
520524
fp_s3select_result_format,
521525
fp_result_header_format,
522526
fp_debug_mesg);
@@ -537,7 +541,7 @@ int RGWSelectObj_ObjStore_S3::run_s3select_on_json(const char* query, const char
537541
s3select_syntax.parse_query(m_sql_query.c_str());
538542
if (s3select_syntax.get_error_description().empty() == false) {
539543
//SQL statement is wrong(syntax).
540-
m_aws_response_handler.send_error_response_rgw_formatter(s3select_syntax_error,
544+
m_aws_response_handler.send_error_response(s3select_syntax_error,
541545
s3select_syntax.get_error_description().c_str(),
542546
s3select_resource_id);
543547
ldpp_dout(this, 10) << "s3-select query: failed to prase query; {" << s3select_syntax.get_error_description() << "}" << dendl;
@@ -559,7 +563,7 @@ int RGWSelectObj_ObjStore_S3::run_s3select_on_json(const char* query, const char
559563
} catch(base_s3select_exception& e) {
560564
ldpp_dout(this, 10) << "S3select: failed to process JSON object: " << e.what() << dendl;
561565
m_aws_response_handler.get_sql_result().append(e.what());
562-
m_aws_response_handler.send_error_response_rgw_formatter(s3select_processTime_error,
566+
m_aws_response_handler.send_error_response(s3select_processTime_error,
563567
e.what(),
564568
s3select_resource_id);
565569
return -EINVAL;
@@ -568,13 +572,12 @@ int RGWSelectObj_ObjStore_S3::run_s3select_on_json(const char* query, const char
568572
m_aws_response_handler.update_total_bytes_returned(length_post_processing - length_before_processing);
569573
if (status < 0) {
570574
//error flow(processing-time)
571-
m_aws_response_handler.send_error_response_rgw_formatter(s3select_processTime_error,
575+
m_aws_response_handler.send_error_response(s3select_processTime_error,
572576
m_s3_json_object.get_error_description().c_str(),
573577
s3select_resource_id);
574578
ldpp_dout(this, 10) << "s3-select query: failed to process query; {" << m_s3_json_object.get_error_description() << "}" << dendl;
575579
return -EINVAL;
576580
}
577-
fp_chunked_transfer_encoding();
578581

579582
if (length_post_processing-length_before_processing != 0) {
580583
m_aws_response_handler.send_success_response();
@@ -726,6 +729,21 @@ void RGWSelectObj_ObjStore_S3::execute(optional_yield y)
726729
#ifdef _ARROW_EXIST
727730
m_rgw_api.m_y = &y;
728731
#endif
732+
733+
if (!m_aws_response_handler.is_set()) {
734+
m_aws_response_handler.set(s, this, fp_chunked_transfer_encoding);
735+
}
736+
737+
if(s->cct->_conf->rgw_disable_s3select == true)
738+
{
739+
std::string error_msg="s3select : is disabled by rgw_disable_s3select configuration parameter";
740+
ldpp_dout(this, 10) << error_msg << dendl;
741+
m_aws_response_handler.send_error_response_rgw_formatter(error_msg.data());
742+
743+
op_ret = -ERR_INVALID_REQUEST;
744+
return;
745+
}
746+
729747
if (m_parquet_type) {
730748
//parquet processing
731749
range_request(0, 4, parquet_magic, y);
@@ -991,6 +1009,7 @@ int RGWSelectObj_ObjStore_S3::json_processing(bufferlist& bl, off_t ofs, off_t l
9911009

9921010
int RGWSelectObj_ObjStore_S3::send_response_data(bufferlist& bl, off_t ofs, off_t len)
9931011
{
1012+
9941013
if (m_scan_range_ind == false){
9951014
m_object_size_for_processing = s->obj_size;
9961015
}
@@ -1005,7 +1024,7 @@ int RGWSelectObj_ObjStore_S3::send_response_data(bufferlist& bl, off_t ofs, off_
10051024
}
10061025
}
10071026
if (!m_aws_response_handler.is_set()) {
1008-
m_aws_response_handler.set(s, this);
1027+
m_aws_response_handler.set(s, this, fp_chunked_transfer_encoding);
10091028
}
10101029
if (len == 0 && s->obj_size != 0) {
10111030
return 0;

src/rgw/rgw_s3select_private.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ class aws_response_handler
9494
void push_header(const char* header_name, const char* header_value);
9595

9696
int create_message(u_int32_t header_len,std::string*);
97+
std::function<void(void)> m_fp_chunk_encoding;
9798

9899
public:
99100
aws_response_handler(req_state* ps, RGWOp* rgwop) : s(ps), m_rgwop(rgwop), total_bytes_returned{0}, processed_size{0}
@@ -110,10 +111,11 @@ class aws_response_handler
110111
return true;
111112
}
112113

113-
void set(req_state* ps, RGWOp* rgwop)
114+
void set(req_state* ps, RGWOp* rgwop, std::function<void(void)>& fp_chunk_encoding)
114115
{
115116
s = ps;
116117
m_rgwop = rgwop;
118+
m_fp_chunk_encoding = fp_chunk_encoding;
117119
}
118120

119121
std::string& get_sql_result();
@@ -150,7 +152,9 @@ class aws_response_handler
150152

151153
void init_stats_response();
152154

153-
void send_error_response(const char* error_message);
155+
void send_error_response(const char* error_code,
156+
const char* error_message,
157+
const char* resource_id);
154158

155159
void send_success_response();
156160

0 commit comments

Comments
 (0)