}
ldpp_dout(dpp, 4) << "Promoted to master zone and committed new period "
<< id << dendl;
- realm.notify_new_period(dpp, *this, y);
return 0;
}
// period must be based on current epoch
}
// set as latest epoch
r = update_latest_epoch(dpp, epoch, y);
- if (r == -EEXIST) {
- // already have this epoch (or a more recent one)
- return 0;
- }
if (r < 0) {
ldpp_dout(dpp, 0) << "failed to set latest epoch: " << cpp_strerror(-r) << dendl;
return r;
}
ldpp_dout(dpp, 4) << "Committed new epoch " << epoch
<< " for period " << id << dendl;
- realm.notify_new_period(dpp, *this, y);
return 0;
}
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab ft=cpp
+#include <optional>
#include "common/errno.h"
#include "rgw_rest_realm.h"
#include "rgw_rest_s3.h"
// POST /admin/realm/period
class RGWOp_Period_Post : public RGWOp_Period_Base {
+ std::optional<RGWRealm> notify_realm;
public:
void execute(optional_yield y) override;
+ void send_response() override;
int check_caps(const RGWUserCaps& caps) override {
return caps.check_cap("zone", RGW_CAP_WRITE);
}
int verify_permission(optional_yield) override {
return check_caps(s->user->get_caps());
}
+
const char* name() const override { return "post_period"; }
RGWOpType get_type() override { return RGW_OP_PERIOD_POST; }
};
// if period id is empty, handle as 'period commit'
if (period.get_id().empty()) {
op_ret = period.commit(this, driver, realm, current_period, error_stream, y);
+ if (op_ret == -EEXIST) {
+ op_ret = 0; // succeed on retries so the op is idempotent
+ return;
+ }
if (op_ret < 0) {
ldpp_dout(this, -1) << "master zone failed to commit period" << dendl;
+ return;
}
+ notify_realm = std::move(realm); // trigger realm reload
return;
}
ldpp_dout(this, 4) << "period " << period.get_id()
<< " is newer than current period " << current_period.get_id()
<< ", updating realm's current period and notifying zone" << dendl;
- realm.notify_new_period(this, period, y);
+ notify_realm = std::move(realm); // trigger realm reload
return;
}
// reflect the period into our local objects
ldpp_dout(this, 4) << "period epoch " << period.get_epoch()
<< " is newer than current epoch " << current_period.get_epoch()
<< ", updating period's latest epoch and notifying zone" << dendl;
- realm.notify_new_period(this, period, y);
+ notify_realm = std::move(realm); // trigger realm reload
// update the period history
period_history->insert(RGWPeriod{period});
}
+void RGWOp_Period_Post::send_response()
+{
+ RGWOp_Period_Base::send_response();
+
+ if (notify_realm) {
+ // trigger realm reload after sending the response, because reload may
+ // race to close this connection
+ notify_realm->notify_new_period(this, period, s->yield);
+ }
+}
+
class RGWHandler_Period : public RGWHandler_Auth_S3 {
protected:
using RGWHandler_Auth_S3::RGWHandler_Auth_S3;
}
ldpp_dout(dpp, 4) << "Promoted to master zone and committed new period "
<< info.id << dendl;
- (void) cfgstore->realm_notify_new_period(dpp, y, info);
return 0;
}
// period must be based on current epoch
// write the period
constexpr bool exclusive = true;
int r = cfgstore->create_period(dpp, y, exclusive, info);
- if (r == -EEXIST) {
- // already have this epoch (or a more recent one)
- return 0;
- }
if (r < 0) {
ldpp_dout(dpp, 0) << "failed to store period: " << cpp_strerror(r) << dendl;
return r;
}
ldpp_dout(dpp, 4) << "Committed new epoch " << info.epoch
<< " for period " << info.id << dendl;
- (void) cfgstore->realm_notify_new_period(dpp, y, info);
return 0;
}