Skip to content

Commit 406a8e8

Browse files
authored
Merge pull request ceph#63160 from yuvalif/wip-yuval-71219
rgw/logging: send flushed object name in API reply
2 parents fd3d6bc + efe4473 commit 406a8e8

File tree

11 files changed

+184
-37
lines changed

11 files changed

+184
-37
lines changed

doc/radosgw/s3/bucketops.rst

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -916,7 +916,8 @@ HTTP Response
916916
Flush Bucket Logging
917917
--------------------
918918

919-
Flushes all logging objects for a given source bucket (logging bucket are written lazily).
919+
Flushes logging object for a given source bucket (if not flushed, the logging objects are written lazily to the log bucket).
920+
Returns the name of the object that was flushed. An empty name will be returned if no object needs to be flushed.
920921

921922
Syntax
922923
~~~~~~
@@ -925,14 +926,24 @@ Syntax
925926

926927
POST /{bucket}?logging HTTP/1.1
927928

929+
Response Entities
930+
~~~~~~~~~~~~~~~~~
931+
932+
Response is XML encoded in the body of the request, in the following format:
933+
934+
::
935+
936+
<PostBucketLoggingOutput xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
937+
<FlushedLoggingObject>string</FlushedLoggingObject>
938+
</PostBucketLoggingOutput>
928939

929940
HTTP Response
930941
~~~~~~~~~~~~~
931942

932943
+---------------+-----------------------+----------------------------------------------------------+
933944
| HTTP Status | Status Code | Description |
934945
+===============+=======================+==========================================================+
935-
| ``201`` | Created | Flushed all logging objects successfully |
946+
| ``201`` | Created | Flushed pending logging object successfully |
936947
+---------------+-----------------------+----------------------------------------------------------+
937948
| ``404`` | NoSuchBucket | The bucket does not exist |
938949
+---------------+-----------------------+----------------------------------------------------------+

examples/rgw/boto3/service-2.sdk-extras.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"responseCode":201
2222
},
2323
"input":{"shape":"PostBucketLoggingRequest"},
24+
"output": {"shape": "PostBucketLoggingOutput"},
2425
"documentationUrl":"https://docs.ceph.com/docs/master/radosgw/s3/bucketops/#post-bucket-logging",
2526
"documentation":"<p>Flushes the logging objects of the buckets.</p>"
2627
},
@@ -392,6 +393,18 @@
392393
}
393394
}
394395
},
396+
"PostBucketLoggingOutput": {
397+
"type":"structure",
398+
"members":{
399+
"FlushedLoggingObject": {
400+
"shape":"FlushedLoggingObject",
401+
"documentation":"<p>Name of the pending logging object that was flushed.</p>"
402+
}
403+
}
404+
},
405+
"FlushedLoggingObject":{
406+
"type":"string"
407+
},
395408
"HeadBucketOutput":{
396409
"type":"structure",
397410
"members":{

src/rgw/driver/rados/rgw_sal_rados.cc

Lines changed: 96 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,56 @@ int RadosBucket::remove_topics(RGWObjVersionTracker* objv_tracker,
10711071
objv_tracker, y);
10721072
}
10731073

1074+
1075+
#define RGW_ATTR_COMMITTED_LOGGING_OBJ RGW_ATTR_PREFIX "committed-logging-obj"
1076+
1077+
int get_committed_logging_object(RadosStore* store,
1078+
const std::string& obj_name_oid,
1079+
const rgw_pool& data_pool,
1080+
optional_yield y,
1081+
const DoutPrefixProvider *dpp,
1082+
std::string& last_committed) {
1083+
librados::IoCtx io_ctx;
1084+
if (const int ret = rgw_init_ioctx(dpp, store->getRados()->get_rados_handle(), data_pool, io_ctx); ret < 0) {
1085+
return -EIO;
1086+
}
1087+
if (!io_ctx.is_valid()) {
1088+
return -EIO;
1089+
}
1090+
bufferlist bl;
1091+
librados::ObjectReadOperation op;
1092+
int rval;
1093+
op.getxattr(RGW_ATTR_COMMITTED_LOGGING_OBJ, &bl, &rval);
1094+
if (const int ret = rgw_rados_operate(dpp, io_ctx, obj_name_oid, std::move(op), nullptr, y); ret < 0) {
1095+
return ret;
1096+
}
1097+
last_committed = bl.to_str();
1098+
return 0;
1099+
}
1100+
1101+
int set_committed_logging_object(RadosStore* store,
1102+
const std::string& obj_name_oid,
1103+
const rgw_pool& data_pool,
1104+
optional_yield y,
1105+
const DoutPrefixProvider *dpp,
1106+
const std::string& last_committed) {
1107+
librados::IoCtx io_ctx;
1108+
if (const int ret = rgw_init_ioctx(dpp, store->getRados()->get_rados_handle(), data_pool, io_ctx); ret < 0) {
1109+
ldpp_dout(dpp, 1) << "ERROR: failed to get IO context when setting last committed logging object name from data pool:" << data_pool.to_str() << dendl;
1110+
return -EIO;
1111+
}
1112+
if (!io_ctx.is_valid()) {
1113+
ldpp_dout(dpp, 1) << "ERROR: invalid IO context when setting last committed logging object name" << dendl;
1114+
return -EIO;
1115+
}
1116+
1117+
bufferlist bl;
1118+
bl.append(last_committed);
1119+
librados::ObjectWriteOperation op;
1120+
op.setxattr(RGW_ATTR_COMMITTED_LOGGING_OBJ, std::move(bl));
1121+
return rgw_rados_operate(dpp, io_ctx, obj_name_oid, std::move(op), y);
1122+
}
1123+
10741124
int RadosBucket::get_logging_object_name(std::string& obj_name,
10751125
const std::string& prefix,
10761126
optional_yield y,
@@ -1129,7 +1179,7 @@ int RadosBucket::set_logging_object_name(const std::string& obj_name,
11291179
objv_tracker,
11301180
ceph::real_time::clock::now(),
11311181
y,
1132-
nullptr);
1182+
no_change_attrs());
11331183
if (ret == -EEXIST) {
11341184
ldpp_dout(dpp, 20) << "INFO: race detected in initializing '" << obj_name_oid << "' with logging object name:'" << obj_name << "'. ret = " << ret << dendl;
11351185
} else if (ret == -ECANCELED) {
@@ -1183,7 +1233,11 @@ int RadosBucket::remove_logging_object(const std::string& obj_name, optional_yie
11831233
y);
11841234
}
11851235

1186-
int RadosBucket::commit_logging_object(const std::string& obj_name, optional_yield y, const DoutPrefixProvider *dpp) {
1236+
int RadosBucket::commit_logging_object(const std::string& obj_name,
1237+
optional_yield y,
1238+
const DoutPrefixProvider *dpp,
1239+
const std::string& prefix,
1240+
std::string* last_committed) {
11871241
rgw_pool data_pool;
11881242
const rgw_obj head_obj{get_key(), obj_name};
11891243
const auto placement_rule = get_placement_rule();
@@ -1193,6 +1247,24 @@ int RadosBucket::commit_logging_object(const std::string& obj_name, optional_yie
11931247
"' when committing logging object" << dendl;
11941248
return -EIO;
11951249
}
1250+
const auto obj_name_oid = bucketlogging::object_name_oid(this, prefix);
1251+
if (last_committed) {
1252+
if (const int ret = get_committed_logging_object(store,
1253+
obj_name_oid,
1254+
data_pool,
1255+
y,
1256+
dpp,
1257+
*last_committed); ret < 0) {
1258+
if (ret != -ENODATA) {
1259+
ldpp_dout(dpp, 1) << "ERROR: failed to get last committed logging object name from bucket '" << get_key() <<
1260+
"' when committing logging object. ret = " << ret << dendl;
1261+
return ret;
1262+
}
1263+
ldpp_dout(dpp, 5) << "WARNING: no last committed logging object name found for bucket '" << get_key() <<
1264+
"' when committing logging object" << dendl;
1265+
last_committed->clear();
1266+
}
1267+
}
11961268

11971269
const auto temp_obj_name = to_temp_object_name(this, obj_name);
11981270
std::map<string, bufferlist> obj_attrs;
@@ -1207,13 +1279,14 @@ int RadosBucket::commit_logging_object(const std::string& obj_name, optional_yie
12071279
y,
12081280
dpp,
12091281
&obj_attrs,
1210-
nullptr); ret < 0 && ret != -ENOENT) {
1211-
ldpp_dout(dpp, 1) << "ERROR: failed to read logging data when committing object '" << temp_obj_name
1212-
<< ". error: " << ret << dendl;
1282+
nullptr); ret < 0) {
1283+
if (ret == -ENOENT) {
1284+
ldpp_dout(dpp, 5) << "WARNING: temporary logging object '" << temp_obj_name << "' does not exists" << dendl;
1285+
} else {
1286+
ldpp_dout(dpp, 1) << "ERROR: failed to read logging data when committing object '" << temp_obj_name
1287+
<< ". error: " << ret << dendl;
1288+
}
12131289
return ret;
1214-
} else if (ret == -ENOENT) {
1215-
ldpp_dout(dpp, 1) << "WARNING: temporary logging object '" << temp_obj_name << "' does not exists" << dendl;
1216-
return 0;
12171290
}
12181291

12191292
uint64_t size = bl_data.length();
@@ -1279,9 +1352,24 @@ int RadosBucket::commit_logging_object(const std::string& obj_name, optional_yie
12791352
"' to bucket '" << get_key() <<"'. error: " << ret << dendl;
12801353
return ret;
12811354
}
1355+
12821356
ldpp_dout(dpp, 20) << "INFO: committed logging object '" << temp_obj_name <<
12831357
"' with size of " << size << " bytes, to bucket '" << get_key() << "' as '" <<
12841358
obj_name << "'" << dendl;
1359+
1360+
if (const int ret = set_committed_logging_object(store,
1361+
obj_name_oid,
1362+
data_pool,
1363+
y,
1364+
dpp,
1365+
obj_name); ret < 0) {
1366+
ldpp_dout(dpp, 5) << "WARNING: object was committed, but we failed to set last committed logging object name. ret = " << ret << dendl;
1367+
} else {
1368+
ldpp_dout(dpp, 20) << "INFO: last committed logging object name was set to '" << obj_name << "'" << dendl;
1369+
}
1370+
if (last_committed) {
1371+
*last_committed = obj_name;
1372+
}
12851373
return 0;
12861374
}
12871375

src/rgw/driver/rados/rgw_sal_rados.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,7 @@ class RadosBucket : public StoreBucket {
803803
optional_yield y,
804804
const DoutPrefixProvider *dpp,
805805
RGWObjVersionTracker* objv_tracker) override;
806-
int commit_logging_object(const std::string& obj_name, optional_yield y, const DoutPrefixProvider *dpp) override;
806+
int commit_logging_object(const std::string& obj_name, optional_yield y, const DoutPrefixProvider *dpp, const std::string& prefix, std::string* last_committed) override;
807807
int remove_logging_object(const std::string& obj_name, optional_yield y, const DoutPrefixProvider *dpp) override;
808808
int write_logging_object(const std::string& obj_name, const std::string& record, optional_yield y, const DoutPrefixProvider *dpp, bool async_completion) override;
809809

src/rgw/radosgw-admin/radosgw-admin.cc

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7832,12 +7832,18 @@ int main(int argc, const char **argv)
78327832
cerr << "ERROR: failed to get pending logging object name from target bucket '" << configuration.target_bucket << "'" << std::endl;
78337833
return -ret;
78347834
}
7835-
const auto old_obj = obj_name;
7835+
std::string old_obj;
78367836
const auto region = driver->get_zone()->get_zonegroup().get_api_name();
7837-
ret = rgw::bucketlogging::rollover_logging_object(configuration, target_bucket, obj_name, dpp(), region, bucket, null_yield, true, &objv_tracker);
7837+
ret = rgw::bucketlogging::rollover_logging_object(configuration, target_bucket, obj_name, dpp(), region, bucket, null_yield, true, &objv_tracker, &old_obj);
78387838
if (ret < 0) {
7839-
cerr << "ERROR: failed to flush pending logging object '" << old_obj
7840-
<< "' to target bucket '" << configuration.target_bucket << "'" << std::endl;
7839+
if (ret == -ENOENT) {
7840+
cerr << "WARNING: no pending logging object '" << obj_name << "'. nothing to flush";
7841+
ret = 0;
7842+
} else {
7843+
cerr << "ERROR: failed flush pending logging object '" << obj_name << "'";
7844+
}
7845+
cerr << " to target bucket '" << configuration.target_bucket << "'. "
7846+
<< " last committed object is '" << old_obj << "'" << std::endl;
78417847
return -ret;
78427848
}
78437849
cout << "flushed pending logging object '" << old_obj

src/rgw/rgw_bucket_logging.cc

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,8 @@ int commit_logging_object(const configuration& conf,
301301
const DoutPrefixProvider *dpp,
302302
rgw::sal::Driver* driver,
303303
const std::string& tenant_name,
304-
optional_yield y) {
304+
optional_yield y,
305+
std::string* last_committed) {
305306
std::string target_bucket_name;
306307
std::string target_tenant_name;
307308
int ret = rgw_parse_url_bucket(conf.target_bucket, tenant_name, target_tenant_name, target_bucket_name);
@@ -319,20 +320,21 @@ int commit_logging_object(const configuration& conf,
319320
<< ret << dendl;
320321
return ret;
321322
}
322-
return commit_logging_object(conf, target_bucket, dpp, y);
323+
return commit_logging_object(conf, target_bucket, dpp, y, last_committed);
323324
}
324325

325326
int commit_logging_object(const configuration& conf,
326327
const std::unique_ptr<rgw::sal::Bucket>& target_bucket,
327328
const DoutPrefixProvider *dpp,
328-
optional_yield y) {
329+
optional_yield y,
330+
std::string* last_committed) {
329331
std::string obj_name;
330332
if (const int ret = target_bucket->get_logging_object_name(obj_name, conf.target_prefix, y, dpp, nullptr); ret < 0) {
331333
ldpp_dout(dpp, 1) << "ERROR: failed to get name of logging object of bucket '" <<
332334
target_bucket->get_key() << "'. ret = " << ret << dendl;
333335
return ret;
334336
}
335-
if (const int ret = target_bucket->commit_logging_object(obj_name, y, dpp); ret <0 ) {
337+
if (const int ret = target_bucket->commit_logging_object(obj_name, y, dpp, conf.target_prefix, last_committed); ret < 0) {
336338
ldpp_dout(dpp, 1) << "ERROR: failed to commit logging object '" << obj_name << "' of bucket '" <<
337339
target_bucket->get_key() << "'. ret = " << ret << dendl;
338340
return ret;
@@ -348,7 +350,8 @@ int rollover_logging_object(const configuration& conf,
348350
const std::unique_ptr<rgw::sal::Bucket>& source_bucket,
349351
optional_yield y,
350352
bool must_commit,
351-
RGWObjVersionTracker* objv_tracker) {
353+
RGWObjVersionTracker* objv_tracker,
354+
std::string* last_committed) {
352355
std::string target_bucket_name;
353356
std::string target_tenant_name;
354357
std::ignore = rgw_parse_url_bucket(conf.target_bucket, target_bucket->get_tenant(), target_tenant_name, target_bucket_name);
@@ -368,7 +371,7 @@ int rollover_logging_object(const configuration& conf,
368371
target_bucket->get_key() << "'. ret = " << ret << dendl;
369372
return ret;
370373
}
371-
if (const int ret = target_bucket->commit_logging_object(old_obj, y, dpp); ret < 0) {
374+
if (const int ret = target_bucket->commit_logging_object(old_obj, y, dpp, conf.target_prefix, last_committed); ret < 0) {
372375
if (must_commit) {
373376
return ret;
374377
}
@@ -476,7 +479,7 @@ int log_record(rgw::sal::Driver* driver,
476479
if (ceph::coarse_real_time::clock::now() > time_to_commit) {
477480
ldpp_dout(dpp, 20) << "INFO: logging object '" << obj_name << "' exceeded its time, will be committed to bucket '" <<
478481
target_bucket_id << "'" << dendl;
479-
if (ret = rollover_logging_object(conf, target_bucket, obj_name, dpp, region, s->bucket, y, false, &objv_tracker); ret < 0) {
482+
if (ret = rollover_logging_object(conf, target_bucket, obj_name, dpp, region, s->bucket, y, false, &objv_tracker, nullptr); ret < 0) {
480483
return ret;
481484
}
482485
} else {
@@ -622,7 +625,7 @@ int log_record(rgw::sal::Driver* driver,
622625
if (ret == -EFBIG) {
623626
ldpp_dout(dpp, 5) << "WARNING: logging object '" << obj_name << "' is full, will be committed to bucket '" <<
624627
target_bucket->get_key() << "'" << dendl;
625-
if (ret = rollover_logging_object(conf, target_bucket, obj_name, dpp, region, s->bucket, y, true, nullptr); ret < 0 ) {
628+
if (ret = rollover_logging_object(conf, target_bucket, obj_name, dpp, region, s->bucket, y, true, nullptr, nullptr); ret < 0 ) {
626629
return ret;
627630
}
628631
if (ret = target_bucket->write_logging_object(obj_name,
@@ -853,7 +856,7 @@ int source_bucket_cleanup(const DoutPrefixProvider* dpp,
853856
return 0;
854857
}
855858
const auto& info = bucket->get_info();
856-
if (const int ret = commit_logging_object(*conf, dpp, driver, info.bucket.tenant, y); ret < 0) {
859+
if (const int ret = commit_logging_object(*conf, dpp, driver, info.bucket.tenant, y, nullptr); ret < 0) {
857860
ldpp_dout(dpp, 5) << "WARNING: could not commit pending logging object of bucket '" <<
858861
bucket->get_key() << "' during cleanup. ret = " << ret << dendl;
859862
} else {

src/rgw/rgw_bucket_logging.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ int log_record(rgw::sal::Driver* driver,
172172
// commit the pending log objec to the log bucket
173173
// and create a new pending log object
174174
// if "must_commit" is "false" the function will return success even if the pending log object was not committed
175+
// if "last_committed" is not null, it will be set to the name of the last committed object
175176
int rollover_logging_object(const configuration& conf,
176177
const std::unique_ptr<rgw::sal::Bucket>& bucket,
177178
std::string& obj_name,
@@ -180,24 +181,29 @@ int rollover_logging_object(const configuration& conf,
180181
const std::unique_ptr<rgw::sal::Bucket>& source_bucket,
181182
optional_yield y,
182183
bool must_commit,
183-
RGWObjVersionTracker* objv_tracker);
184+
RGWObjVersionTracker* objv_tracker,
185+
std::string* last_committed);
184186

185187
// commit the pending log object to the log bucket
186188
// use this for cleanup, when new pending object is not needed
187189
// and target bucket is known
190+
// if "last_committed" is not null, it will be set to the name of the last committed object
188191
int commit_logging_object(const configuration& conf,
189192
const std::unique_ptr<rgw::sal::Bucket>& target_bucket,
190193
const DoutPrefixProvider *dpp,
191-
optional_yield y);
194+
optional_yield y,
195+
std::string* last_committed);
192196

193197
// commit the pending log object to the log bucket
194198
// use this for cleanup, when new pending object is not needed
195199
// and target bucket shoud be loaded based on the configuration
200+
// if "last_committed" is not null, it will be set to the name of the last committed object
196201
int commit_logging_object(const configuration& conf,
197202
const DoutPrefixProvider *dpp,
198203
rgw::sal::Driver* driver,
199204
const std::string& tenant_name,
200-
optional_yield y);
205+
optional_yield y,
206+
std::string* last_committed);
201207

202208
// return the oid of the object holding the name of the temporary logging object
203209
// bucket - log bucket

0 commit comments

Comments
 (0)