@@ -328,14 +328,6 @@ int commit_logging_object(const configuration& conf,
328328 << ret << dendl;
329329 return ret;
330330 }
331- return commit_logging_object (conf, target_bucket, dpp, y, last_committed);
332- }
333-
334- int commit_logging_object (const configuration& conf,
335- const std::unique_ptr<rgw::sal::Bucket>& target_bucket,
336- const DoutPrefixProvider *dpp,
337- optional_yield y,
338- std::string* last_committed) {
339331 std::string obj_name;
340332 if (const int ret = target_bucket->get_logging_object_name (obj_name, conf.target_prefix , y, dpp, nullptr ); ret < 0 ) {
341333 ldpp_dout (dpp, 1 ) << " ERROR: failed to get name of logging object of logging bucket '" <<
@@ -509,6 +501,12 @@ int log_record(rgw::sal::Driver* driver,
509501 return ret;
510502 }
511503
504+ // make sure that the logging source attribute is up-to-date
505+ if (ret = update_bucket_logging_sources (dpp, target_bucket, s->bucket ->get_key (), true , y); ret < 0 ) {
506+ ldpp_dout (dpp, 5 ) << " WARNING: could not update bucket logging source '" <<
507+ s->bucket ->get_key () << " ' in logging bucket '" << target_bucket_id << " ' attribute, during record logging. ret = " << ret << dendl;
508+ }
509+
512510 const auto region = driver->get_zone ()->get_zonegroup ().get_api_name ();
513511 std::string obj_name;
514512 RGWObjVersionTracker objv_tracker;
@@ -795,8 +793,7 @@ int update_bucket_logging_sources(const DoutPrefixProvider* dpp, std::unique_ptr
795793 ldpp_dout (dpp, 5 ) << " WARNING: failed to decode logging sources attribute '" << RGW_ATTR_BUCKET_LOGGING_SOURCES
796794 << " ' for bucket '" << bucket->get_key () << " ' when updating logging sources. error: " << err.what () << dendl;
797795 }
798- ldpp_dout (dpp, 20 ) << " INFO: logging source '" << src_bucket_id << " ' already " <<
799- (add ? " added to" : " removed from" ) << " bucket '" << bucket->get_key () << " '" << dendl;
796+ // no change
800797 return 0 ;
801798 }, y);
802799}
@@ -810,53 +807,59 @@ int bucket_deletion_cleanup(const DoutPrefixProvider* dpp,
810807 // and also delete the object holding the pending object name
811808 auto & attrs = bucket->get_attrs ();
812809 if (const auto iter = attrs.find (RGW_ATTR_BUCKET_LOGGING_SOURCES); iter != attrs.end ()) {
810+ source_buckets sources;
813811 try {
814- source_buckets sources;
815812 ceph::decode (sources, iter->second );
816- for (const auto & source : sources) {
817- std::unique_ptr<rgw::sal::Bucket> src_bucket;
818- if (const int ret = driver->load_bucket (dpp, source, &src_bucket, y); ret < 0 ) {
819- ldpp_dout (dpp, 5 ) << " WARNING: failed to get logging source bucket '" << source << " ' for logging bucket '" <<
813+ } catch (buffer::error& err) {
814+ ldpp_dout (dpp, 5 ) << " WARNING: failed to decode logging sources attribute '" << RGW_ATTR_BUCKET_LOGGING_SOURCES
815+ << " ' for logging bucket '" << bucket->get_key () << " '. error: " << err.what () << dendl;
816+ return -EIO;
817+ }
818+ // since we removed the attribute, we should not return error code from now on
819+ // any retry, would find no attribute and return success
820+ for (const auto & source : sources) {
821+ std::unique_ptr<rgw::sal::Bucket> src_bucket;
822+ if (const int ret = driver->load_bucket (dpp, source, &src_bucket, y); ret < 0 ) {
823+ ldpp_dout (dpp, 5 ) << " WARNING: failed to get logging source bucket '" << source << " ' for logging bucket '" <<
824+ bucket->get_key () << " ' during cleanup. ret = " << ret << dendl;
825+ continue ;
826+ }
827+ auto & src_attrs = src_bucket->get_attrs ();
828+ if (const auto iter = src_attrs.find (RGW_ATTR_BUCKET_LOGGING); iter != src_attrs.end ()) {
829+ configuration conf;
830+ try {
831+ auto bl_iter = iter->second .cbegin ();
832+ decode (conf, bl_iter);
833+ } catch (buffer::error& err) {
834+ ldpp_dout (dpp, 5 ) << " WARNING: failed to decode logging attribute '" << RGW_ATTR_BUCKET_LOGGING
835+ << " ' of bucket '" << src_bucket->get_key () << " ' during cleanup. error: " << err.what () << dendl;
836+ continue ;
837+ }
838+ std::string obj_name;
839+ RGWObjVersionTracker objv;
840+ if (const int ret = bucket->get_logging_object_name (obj_name, conf.target_prefix , y, dpp, &objv); ret < 0 ) {
841+ ldpp_dout (dpp, 5 ) << " WARNING: failed to get logging object name for logging bucket '" << bucket->get_key () <<
842+ " ' during cleanup. ret = " << ret << dendl;
843+ continue ;
844+ }
845+ if (const int ret = bucket->remove_logging_object_name (conf.target_prefix , y, dpp, &objv); ret < 0 ) {
846+ ldpp_dout (dpp, 5 ) << " WARNING: failed to delete object holding bucket logging object name for logging bucket '" <<
820847 bucket->get_key () << " ' during cleanup. ret = " << ret << dendl;
821848 continue ;
822849 }
823- auto & src_attrs = src_bucket->get_attrs ();
824- if (const auto iter = src_attrs.find (RGW_ATTR_BUCKET_LOGGING); iter != src_attrs.end ()) {
825- configuration conf;
826- try {
827- auto bl_iter = iter->second .cbegin ();
828- decode (conf, bl_iter);
829- std::string obj_name;
830- RGWObjVersionTracker objv;
831- if (const int ret = bucket->get_logging_object_name (obj_name, conf.target_prefix , y, dpp, &objv); ret < 0 ) {
832- ldpp_dout (dpp, 5 ) << " WARNING: failed to get logging object name for logging bucket '" << bucket->get_key () <<
833- " ' during cleanup. ret = " << ret << dendl;
834- continue ;
835- }
836- if (const int ret = bucket->remove_logging_object (obj_name, y, dpp); ret < 0 ) {
837- ldpp_dout (dpp, 5 ) << " WARNING: failed to delete pending logging object '" << obj_name << " ' for logging bucket '" <<
838- bucket->get_key () << " ' during cleanup. ret = " << ret << dendl;
839- continue ;
840- }
841- ldpp_dout (dpp, 20 ) << " INFO: successfully deleted pending logging object '" << obj_name << " ' from deleted logging bucket '" <<
842- bucket->get_key () << " '" << dendl;
843- if (const int ret = bucket->remove_logging_object_name (conf.target_prefix , y, dpp, &objv); ret < 0 ) {
844- ldpp_dout (dpp, 5 ) << " WARNING: failed to delete object holding bucket logging object name for logging bucket '" <<
845- bucket->get_key () << " ' during cleanup. ret = " << ret << dendl;
846- continue ;
847- }
848- ldpp_dout (dpp, 20 ) << " INFO: successfully deleted object holding bucket logging object name from deleted logging bucket '" <<
849- bucket->get_key () << " '" << dendl;
850- } catch (buffer::error& err) {
851- ldpp_dout (dpp, 5 ) << " WARNING: failed to decode logging attribute '" << RGW_ATTR_BUCKET_LOGGING
852- << " ' of bucket '" << src_bucket->get_key () << " ' during cleanup. error: " << err.what () << dendl;
853- }
850+ ldpp_dout (dpp, 20 ) << " INFO: successfully deleted object holding bucket logging object name from deleted logging bucket '" <<
851+ bucket->get_key () << " '" << dendl;
852+ if (const int ret = bucket->remove_logging_object (obj_name, y, dpp); ret < 0 ) {
853+ ldpp_dout (dpp, 5 ) << " WARNING: failed to delete pending logging object '" << obj_name << " ' for logging bucket '" <<
854+ bucket->get_key () << " ' during cleanup. ret = " << ret << dendl;
855+ continue ;
854856 }
857+ ldpp_dout (dpp, 20 ) << " INFO: successfully deleted pending logging object '" << obj_name << " ' from deleted logging bucket '" <<
858+ bucket->get_key () << " '" << dendl;
859+ } else {
860+ ldpp_dout (dpp, 5 ) << " WARNING: no logging attribute '" << RGW_ATTR_BUCKET_LOGGING
861+ << " ' found in logging source bucket '" << src_bucket->get_key () << " ' during cleanup" << dendl;
855862 }
856- } catch (buffer::error& err) {
857- ldpp_dout (dpp, 5 ) << " WARNING: failed to decode logging sources attribute '" << RGW_ATTR_BUCKET_LOGGING_SOURCES
858- << " ' for logging bucket '" << bucket->get_key () << " '. error: " << err.what () << dendl;
859- return -EIO;
860863 }
861864 }
862865
@@ -881,7 +884,7 @@ int source_bucket_cleanup(const DoutPrefixProvider* dpp,
881884 conf = std::move (tmp_conf);
882885 } catch (buffer::error& err) {
883886 ldpp_dout (dpp, 5 ) << " WARNING: failed to decode existing logging attribute '" << RGW_ATTR_BUCKET_LOGGING
884- << " ' of bucket '" << bucket->get_key () << " ' during cleanup. error: " << err.what () << dendl;
887+ << " ' of bucket '" << bucket->get_key () << " ' during source cleanup. error: " << err.what () << dendl;
885888 return -EIO;
886889 }
887890 if (remove_attr) {
@@ -894,34 +897,67 @@ int source_bucket_cleanup(const DoutPrefixProvider* dpp,
894897 }, y); ret < 0 ) {
895898 if (remove_attr) {
896899 ldpp_dout (dpp, 5 ) << " WARNING: failed to remove logging attribute '" << RGW_ATTR_BUCKET_LOGGING <<
897- " ' from bucket '" << bucket->get_key () << " ' during cleanup. ret = " << ret << dendl;
900+ " ' from bucket '" << bucket->get_key () << " ' during source cleanup. ret = " << ret << dendl;
898901 }
899902 return ret;
900903 }
904+ if (last_committed) {
905+ last_committed->clear ();
906+ }
901907 if (!conf) {
902908 // no logging attribute found
903909 return 0 ;
904910 }
905- const auto & info = bucket->get_info ();
906- if (const int ret = commit_logging_object (*conf, dpp, driver, info.bucket .tenant , y, last_committed); ret < 0 ) {
907- ldpp_dout (dpp, 5 ) << " WARNING: could not commit pending logging object of bucket '" <<
908- bucket->get_key () << " ' during cleanup. ret = " << ret << dendl;
909- } else {
910- ldpp_dout (dpp, 20 ) << " INFO: successfully committed pending logging object of bucket '" << bucket->get_key () << " '" << dendl;
911- }
911+ // since we removed the attribute, we should not return error code from now on
912+ // any retry, would find no attribute and return success
912913 rgw_bucket target_bucket_id;
914+ const auto & info = bucket->get_info ();
913915 if (const int ret = get_bucket_id (conf->target_bucket , info.bucket .tenant , target_bucket_id); ret < 0 ) {
914916 ldpp_dout (dpp, 5 ) << " WARNING: failed to parse logging bucket '" <<
915- conf->target_bucket << " ' during cleanup. ret = " << ret << dendl;
917+ conf->target_bucket << " ' during source cleanup. ret = " << ret << dendl;
918+ return 0 ;
919+ }
920+ std::unique_ptr<rgw::sal::Bucket> target_bucket;
921+ const int ret = driver->load_bucket (dpp, target_bucket_id, &target_bucket, y);
922+ if (ret < 0 ) {
923+ ldpp_dout (dpp, 5 ) << " WARNING: failed to get logging bucket '" << target_bucket_id <<
924+ " ' when doing source cleanup. ret = " << ret << dendl;
916925 return 0 ;
917926 }
918- if (const int ret = update_bucket_logging_sources (dpp, driver, target_bucket_id , bucket->get_key (), false , y); ret < 0 ) {
927+ if (const int ret = update_bucket_logging_sources (dpp, target_bucket , bucket->get_key (), false , y); ret < 0 ) {
919928 ldpp_dout (dpp, 5 ) << " WARNING: could not update bucket logging source '" <<
920- bucket->get_key () << " ' during cleanup. ret = " << ret << dendl;
929+ bucket->get_key () << " ' in logging bucket '" << target_bucket_id << " ' attribute, during source cleanup. ret = " << ret << dendl;
930+ }
931+ std::string obj_name;
932+ RGWObjVersionTracker objv;
933+ if (const int ret = target_bucket->get_logging_object_name (obj_name, conf->target_prefix , y, dpp, &objv); ret < 0 ) {
934+ ldpp_dout (dpp, 5 ) << " WARNING: failed to get logging object name for logging bucket '" << bucket->get_key () <<
935+ " ' during source cleanup. ret = " << ret << dendl;
936+ // if name cannot be fetched, we should not commit or remove the object holding the name
937+ // it is better to leak an object than to cause a possible data loss
921938 return 0 ;
922939 }
923- ldpp_dout (dpp, 20 ) << " INFO: successfully updated bucket logging source '" <<
924- bucket->get_key () << " ' during cleanup" << dendl;
940+ if (const int ret = target_bucket->remove_logging_object_name (conf->target_prefix , y, dpp, &objv); ret < 0 ) {
941+ ldpp_dout (dpp, 5 ) << " WARNING: failed to delete object holding bucket logging object name for bucket '" <<
942+ bucket->get_key () << " ' during source cleanup. ret = " << ret << dendl;
943+ // this could be because of a race someone else trying to commit the object
944+ // (another bucket cleanup with shared prefix, rollover or an explicit commit)
945+ // and since committing the object twice will cause data loss, we should not try to commit it here
946+ return 0 ;
947+ }
948+ ldpp_dout (dpp, 20 ) << " INFO: successfully deleted object holding bucket logging object name for bucket '" <<
949+ bucket->get_key () << " ' during source cleanup" << dendl;
950+ // since the object holding the name was deleted, we cannot fetch the last commited name from it
951+ if (const int ret = target_bucket->commit_logging_object (obj_name, y, dpp, conf->target_prefix , nullptr ); ret < 0 ) {
952+ ldpp_dout (dpp, 5 ) << " WARNING: could not commit pending logging object of bucket '" <<
953+ bucket->get_key () << " ' during source cleanup. ret = " << ret << dendl;
954+ return 0 ;
955+ }
956+ ldpp_dout (dpp, 20 ) << " INFO: successfully committed pending logging object of bucket '" <<
957+ bucket->get_key () << " ' during source cleanup. ret = " << ret << dendl;
958+ if (last_committed) {
959+ *last_committed = obj_name;
960+ }
925961 return 0 ;
926962}
927963
0 commit comments