return (location_key < e.location_key);
}
+ bool operator==(const rgw_zone_set_entry& e) const {
+ return zone == e.zone && location_key == e.location_key;
+ }
+
rgw_zone_set_entry() {}
rgw_zone_set_entry(const std::string& _zone,
std::optional<std::string> _location_key) : zone(_zone),
int ret = conn->get_obj(dpp, user_id, info, src_obj, pmod, unmod_ptr,
dest_mtime_weight.zone_short_id, dest_mtime_weight.pg_ver,
prepend_meta, get_op, rgwx_stat,
- sync_manifest, skip_decrypt, sync_cloudtiered,
+ sync_manifest, skip_decrypt, nullptr, sync_cloudtiered,
true, &cb, &in_stream_req);
if (ret < 0) {
return ret;
const real_time *pmod = mod_ptr;
obj_time_weight dest_mtime_weight;
+ rgw_zone_set_entry dst_zone_trace(svc.zone->get_zone().id, dest_bucket_info.bucket.get_key());
if (copy_if_newer) {
/* need to get mtime for destination */
ret = conn->get_obj(dpp, user_id, info, src_obj, pmod, unmod_ptr,
dest_mtime_weight.zone_short_id, dest_mtime_weight.pg_ver,
prepend_meta, get_op, rgwx_stat,
- sync_manifest, skip_decrypt, sync_cloudtiered,
- true,
+ sync_manifest, skip_decrypt, &dst_zone_trace,
+ sync_cloudtiered, true,
&cb, &in_stream_req);
if (ret < 0) {
goto set_err_state;
filter = &*decompress;
}
+ attr_iter = attrs.find(RGW_ATTR_OBJ_REPLICATION_TRACE);
+ if (attr_iter != attrs.end()) {
+ try {
+ std::vector<rgw_zone_set_entry> zones;
+ auto p = attr_iter->second.cbegin();
+ decode(zones, p);
+ for (const auto& zone: zones) {
+ if (zone == dst_zone_trace) {
+ op_ret = -ERR_NOT_MODIFIED;
+ ldpp_dout(this, 4) << "Object already has been copied to this destination. Returning "
+ << op_ret << dendl;
+ goto done_err;
+ }
+ }
+ } catch (const buffer::error&) {}
+ }
+
if (get_type() == RGW_OP_GET_OBJ && get_data) {
op_ret = handle_cloudtier_obj(attrs, sync_cloudtiered);
if (op_ret < 0) {
std::string lo_etag;
bool rgwx_stat; /* extended rgw stat operation */
std::string version_id;
+ rgw_zone_set_entry dst_zone_trace;
// compression attrs
RGWCompressionInfo cs_info;
uint32_t mod_zone_id, uint64_t mod_pg_ver,
bool prepend_metadata, bool get_op, bool rgwx_stat,
bool sync_manifest, bool skip_decrypt,
- bool sync_cloudtiered,
+ rgw_zone_set_entry *dst_zone_trace, bool sync_cloudtiered,
bool send, RGWHTTPStreamRWRequest::ReceiveCB *cb, RGWRESTStreamRWRequest **req)
{
get_obj_params params;
params.sync_manifest = sync_manifest;
params.skip_decrypt = skip_decrypt;
params.sync_cloudtiered = sync_cloudtiered;
+ params.dst_zone_trace = dst_zone_trace;
params.cb = cb;
return get_obj(dpp, obj, params, send, req);
}
if (in_params.skip_decrypt) {
params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "skip-decrypt", ""));
}
+ if (in_params.dst_zone_trace) {
+ params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "if-not-replicated-to", in_params.dst_zone_trace->to_str()));
+ }
if (!obj.key.instance.empty()) {
params.push_back(param_pair_t("versionId", obj.key.instance));
}
bool range_is_set{false};
uint64_t range_start{0};
uint64_t range_end{0};
+ rgw_zone_set_entry *dst_zone_trace{nullptr};
};
int get_obj(const DoutPrefixProvider *dpp, const rgw_obj& obj, const get_obj_params& params, bool send, RGWRESTStreamRWRequest **req);
const ceph::real_time *mod_ptr, const ceph::real_time *unmod_ptr,
uint32_t mod_zone_id, uint64_t mod_pg_ver,
bool prepend_metadata, bool get_op, bool rgwx_stat, bool sync_manifest,
- bool skip_decrypt, bool sync_cloudtiered,
+ bool skip_decrypt, rgw_zone_set_entry *dst_zone_trace, bool sync_cloudtiered,
bool send, RGWHTTPStreamRWRequest::ReceiveCB *cb, RGWRESTStreamRWRequest **req);
int complete_request(RGWRESTStreamRWRequest *req,
std::string *etag,
// multisite sync requests should fetch cloudtiered objects
sync_cloudtiered = s->info.args.exists(RGW_SYS_PARAM_PREFIX "sync-cloudtiered");
+ dst_zone_trace = s->info.args.get(RGW_SYS_PARAM_PREFIX "if-not-replicated-to");
+
return RGWGetObj_ObjStore::get_params(y);
}