#include "services/svc_sys_obj.h"
#include "services/svc_bucket.h"
-#include <string_view>
-using namespace std;
struct rgw_http_param_pair;
class RGWRESTConn;
rgw_obj_key key;
bool is_latest;
real_time mtime;
- string etag;
+ std::string etag;
uint64_t size;
- string storage_class;
+ std::string storage_class;
rgw_bucket_entry_owner owner;
uint64_t versioned_epoch;
- string rgw_tag;
+ std::string rgw_tag;
bucket_list_entry() : delete_marker(false), is_latest(false), size(0), versioned_epoch(0) {}
JSONDecoder::decode_json("Key", key.name, obj);
JSONDecoder::decode_json("VersionId", key.instance, obj);
JSONDecoder::decode_json("IsLatest", is_latest, obj);
- string mtime_str;
+ std::string mtime_str;
JSONDecoder::decode_json("RgwxMtime", mtime_str, obj);
struct tm t;
};
struct bucket_unordered_list_result {
- string name;
- string prefix;
+ std::string name;
+ std::string prefix;
int max_keys;
bool is_truncated;
bool allow_unordered;
- list<bucket_list_entry> entries;
+ std::list<bucket_list_entry> entries;
bucket_unordered_list_result() : max_keys(0), is_truncated(false) {}
const rgw_bucket& bucket;
RGWHTTPManager* http;
std::vector<rgw_zone_id> zids;
- vector<bucket_unordered_list_result>& peer_result;
+ std::vector<bucket_unordered_list_result>& peer_result;
public:
RGWStatRemoteBucketCR(const DoutPrefixProvider *dpp,
return r;
}
-
+
+int get_zone_ids(const DoutPrefixProvider *dpp,
+ rgw::sal::RadosStore* const driver,
+ const rgw_zone_id source_zone,
+ const rgw_bucket& bucket,
+ std::vector<rgw_zone_id>& zids,
+ optional_yield y)
+{
+ RGWBucketSyncPolicyHandlerRef source_handler;
+ int ret = driver->get_sync_policy_handler(dpp, source_zone, bucket, &source_handler, y);
+ if (ret < 0) {
+ ldpp_dout(dpp, 10) << "failed to get bucket sync policy handler (r=" << ret << ")" << dendl;
+ return ret;
+ }
+
+ auto all_dests = source_handler->get_all_dests();
+ rgw_zone_id last_zid;
+ for (auto& diter : all_dests) {
+ const auto& zid = diter.first;
+ if (zid == last_zid) {
+ continue;
+ }
+ last_zid = zid;
+ zids.push_back(zid);
+ }
+ return 0;
+}
+
+int list_remote_buckets(const DoutPrefixProvider *dpp,
+ rgw::sal::RadosStore* const driver,
+ const rgw_zone_id source_zone,
+ const rgw_bucket& bucket,
+ optional_yield y)
+{
+
+ std::vector<rgw_zone_id> zids;
+ int ret = get_zone_ids(dpp, driver, source_zone, bucket, zids, y);
+ if (ret < 0) {
+ ldpp_dout(dpp, 10) << "failed to get remote zones (r=" << ret << ")" << dendl;
+ return ret;
+ }
+
+ std::vector<bucket_unordered_list_result> peer_status;
+ peer_status.resize(zids.size());
+
+ RGWCoroutinesManager crs(driver->ctx(), driver->getRados()->get_cr_registry());
+ RGWHTTPManager http(driver->ctx(), crs.get_completion_mgr());
+ ret = http.start();
+ if (ret < 0) {
+ ldpp_dout(dpp, 0) << "failed in http_manager.start() ret=" << ret << dendl;
+ return ret;
+ }
+
+ ret = crs.run(dpp, new RGWStatRemoteBucketCR(dpp, driver, source_zone, bucket, &http, zids, peer_status));
+ if (ret < 0) {
+ ldpp_dout(dpp, 0) << "failed to fetch remote bucket stats " << cpp_strerror(ret) << dendl;
+ return ret;
+ }
+
+ for (const auto& list_result: peer_status) {
+ auto entries_iter = list_result.entries.begin();
+ for (; entries_iter != list_result.entries.end(); ++entries_iter) {
+ std::string ns;
+ rgw_obj_key obj;
+
+ if (rgw_obj_key::oid_to_key_in_ns(entries_iter->key.name, &obj, ns)) {
+ return -ENOTEMPTY;
+ }
+ }
+ }
+ return 0;
+}
+
/**
* Delete a bucket.
* bucket: the name of the bucket to delete
// delete_bucket checks for objects in the bucket on other zones,
// if there is bucket sync policy configured, by doing unordered
- // listing with max_key=1. we don't prevent users from
- // deleting a bucket if there are any errors in this block
- // except if we found objects in another zone.
+ // listing with max_key=1. if objects are found, don't delete the bucket.
if (svc.zone->is_syncing_bucket_meta(bucket)) {
auto bs_policy = bucket_info.sync_policy;
if (bs_policy) {
- ldpp_dout(dpp, 10) << "bucket policy exists" << dendl;
+ ldpp_dout(dpp, 10) << "bucket policy exists. listing remote zones" << dendl;
const rgw_zone_id source_zone = svc.zone->get_zone_params().get_id();
- RGWBucketSyncPolicyHandlerRef source_handler;
- int ret = driver->get_sync_policy_handler(dpp, source_zone, bucket, &source_handler, y);
- if (ret < 0) {
- ldpp_dout(dpp, 10) << "could not get bucket sync policy handler (r=" << ret << ")" << dendl;
- }
-
- auto all_dests = source_handler->get_all_dests();
- std::vector<rgw_zone_id> zids;
- rgw_zone_id last_zid;
- for (auto& diter : all_dests) {
- const auto& zid = diter.first;
- if (zid == last_zid) {
- continue;
- }
- last_zid = zid;
- zids.push_back(zid);
- }
-
- std::vector<bucket_unordered_list_result> peer_status;
- peer_status.resize(zids.size());
-
- RGWCoroutinesManager crs(driver->ctx(), driver->getRados()->get_cr_registry());
- RGWHTTPManager http(driver->ctx(), crs.get_completion_mgr());
- ret = http.start();
- if (ret < 0) {
- ldpp_dout(dpp, 0) << "failed in http_manager.start() ret=" << ret << dendl;
- }
- ret = crs.run(dpp, new RGWStatRemoteBucketCR(dpp, driver, source_zone, bucket, &http, zids, peer_status));
- if (ret < 0) {
- ldpp_dout(dpp, 0) << "failed to fetch remote bucket stats " << cpp_strerror(ret) << dendl;
- }
-
- for (const auto& list_result: peer_status) {
- auto entries_iter = list_result.entries.begin();
- for (; entries_iter != list_result.entries.end(); ++entries_iter) {
- std::string ns;
- rgw_obj_key obj;
-
- if (rgw_obj_key::oid_to_key_in_ns(entries_iter->key.name, &obj, ns)) {
- ldpp_dout(dpp, 0) << "cannot delete bucket. objects exist in the bucket in another zone " << dendl;
- return -ENOTEMPTY;
- }
- }
+ r = list_remote_buckets(dpp, driver, source_zone, bucket, y);
+ if (r == -ENOTEMPTY) {
+ ldpp_dout(dpp, 0) << "ERROR: cannot delete bucket. objects exist in the bucket on another zone " << dendl;
+ return r;
+ } else if (r < 0) {
+ ldpp_dout(dpp, 10) << "failed to list remote buckets" << dendl;
+ // don't return.
}
}
}