99#include " rgw_sal.h"
1010#include " rgw_op.h"
1111#include " rgw_auth_s3.h"
12+ #include < boost/lexical_cast.hpp>
1213
1314#define dout_subsys ceph_subsys_rgw
1415
@@ -171,6 +172,7 @@ std::string configuration::to_json_str() const {
171172 return ss.str ();
172173}
173174
175+ // create a random string of N characters
174176template <size_t N>
175177std::string unique_string () {
176178 static const std::string possible_characters{" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXY" };
@@ -183,6 +185,27 @@ std::string unique_string() {
183185 return str;
184186}
185187
188+ // create an incremental string of N characters if possible
189+ // fallback to a random string of N characters if not
190+ template <size_t N>
191+ std::string incremental_string (const DoutPrefixProvider *dpp, std::optional<std::string> old_name) {
192+ // for the fist time we create a string of zeros
193+ if (!old_name) {
194+ return std::string (N, ' 0' );
195+ }
196+ const auto str_counter = old_name->substr (old_name->length () - N+1 , N);
197+ try {
198+ auto counter = boost::lexical_cast<unsigned long >(str_counter);
199+ ++counter;
200+ static const auto format = fmt::format (" {{:0>{}}}" , N);
201+ return fmt::vformat (format, fmt::make_format_args (counter));
202+ } catch (const boost::bad_lexical_cast& e) {
203+ ldpp_dout (dpp, 5 ) << " WARNING: failed to convert string '" << str_counter <<
204+ " ' to counter. " <<e.what () << " . will create random temporary logging file name" << dendl;
205+ return unique_string<N>();
206+ }
207+ }
208+
186209constexpr size_t UniqueStringLength = 16 ;
187210
188211ceph::coarse_real_time time_from_name (const std::string& obj_name, const DoutPrefixProvider *dpp) {
@@ -220,13 +243,13 @@ int new_logging_object(const configuration& conf,
220243 std::string& obj_name,
221244 const DoutPrefixProvider *dpp,
222245 optional_yield y,
223- bool init_obj ,
246+ std::optional<std::string> old_name ,
224247 RGWObjVersionTracker* objv_tracker) {
225248 const auto tt = ceph::coarse_real_time::clock::to_time_t (ceph::coarse_real_time::clock::now ());
226249 std::tm t{};
227250 localtime_r (&tt, &t);
228251
229- const auto unique = unique_string <UniqueStringLength>();
252+ const auto unique = incremental_string <UniqueStringLength>(dpp, old_name );
230253
231254 switch (conf.obj_key_format ) {
232255 case KeyFormat::Simple:
@@ -251,7 +274,7 @@ int new_logging_object(const configuration& conf,
251274 break ;
252275 }
253276 const auto & target_bucket_id = target_bucket->get_key ();
254- int ret = target_bucket->set_logging_object_name (obj_name, conf.target_prefix , y, dpp, init_obj , objv_tracker);
277+ int ret = target_bucket->set_logging_object_name (obj_name, conf.target_prefix , y, dpp, (old_name == std:: nullopt ) , objv_tracker);
255278 if (ret == -EEXIST || ret == -ECANCELED) {
256279 if (ret = target_bucket->get_logging_object_name (obj_name, conf.target_prefix , y, dpp, nullptr ); ret < 0 ) {
257280 ldpp_dout (dpp, 1 ) << " ERROR: failed to get name of logging object of bucket '" <<
@@ -330,7 +353,7 @@ int rollover_logging_object(const configuration& conf,
330353 return -EINVAL;
331354 }
332355 const auto old_obj = obj_name;
333- const int ret = new_logging_object (conf, target_bucket, obj_name, dpp, y, false , objv_tracker);
356+ const int ret = new_logging_object (conf, target_bucket, obj_name, dpp, y, old_obj , objv_tracker);
334357 if (ret == -ECANCELED) {
335358 ldpp_dout (dpp, 20 ) << " INFO: rollover already performed for object '" << old_obj << " ' to logging bucket '" <<
336359 target_bucket->get_key () << " '. ret = " << ret << dendl;
@@ -455,7 +478,7 @@ int log_record(rgw::sal::Driver* driver,
455478 }
456479 } else if (ret == -ENOENT) {
457480 // try to create the temporary log object for the first time
458- ret = new_logging_object (conf, target_bucket, obj_name, dpp, y, true , nullptr );
481+ ret = new_logging_object (conf, target_bucket, obj_name, dpp, y, std:: nullopt , nullptr );
459482 if (ret == 0 ) {
460483 ldpp_dout (dpp, 20 ) << " INFO: first time logging for bucket '" << target_bucket_id << " ' and prefix '" <<
461484 conf.target_prefix << " '" << dendl;
0 commit comments