namespace rgw::putobj {
+/*
+ * For the cloudtiered objects, update the object manifest with the
+ * cloudtier config info read from the attrs.
+ * Since these attrs are used internally for only replication, do not store them
+ * in the head object.
+ */
+void read_cloudtier_info_from_attrs(rgw::sal::Attrs& attrs, RGWObjCategory& category,
+ RGWObjManifest& manifest) {
+ auto attr_iter = attrs.find(RGW_ATTR_CLOUD_TIER_TYPE);
+ if (attr_iter != attrs.end()) {
+ auto i = attr_iter->second;
+ string m = i.to_str();
+
+ if (m == "cloud-s3") {
+ category = RGWObjCategory::CloudTiered;
+ manifest.set_tier_type("cloud-s3");
+
+ auto config_iter = attrs.find(RGW_ATTR_CLOUD_TIER_CONFIG);
+ if (config_iter != attrs.end()) {
+ auto i = config_iter->second.cbegin();
+ RGWObjTier tier_config;
+
+ try {
+ using ceph::decode;
+ decode(tier_config, i);
+ manifest.set_tier_config(tier_config);
+ attrs.erase(config_iter);
+ } catch (buffer::error& err) {
+ }
+ }
+ }
+ attrs.erase(attr_iter);
+ }
+}
+
int HeadObjectProcessor::process(bufferlist&& data, uint64_t logical_offset)
{
const bool flush = (data.length() == 0);
obj_op.meta.zones_trace = zones_trace;
obj_op.meta.modify_tail = true;
+ read_cloudtier_info_from_attrs(attrs, obj_op.meta.category, manifest);
+
r = obj_op.write_meta(dpp, actual_size, accounted_size, attrs, y);
if (r < 0) {
if (r == -ETIMEDOUT) {
}
}
+/*
+ * GET on CloudTiered objects is processed only when sent from the sync client.
+ * In all other cases, fail with `ERR_INVALID_OBJECT_STATE`.
+ */
+int handle_cloudtier_obj(rgw::sal::Attrs& attrs, bool sync_cloudtiered) {
+ int op_ret = 0;
+ auto attr_iter = attrs.find(RGW_ATTR_MANIFEST);
+ if (attr_iter != attrs.end()) {
+ RGWObjManifest m;
+ try {
+ decode(m, attr_iter->second);
+ if (m.get_tier_type() == "cloud-s3") {
+ if (!sync_cloudtiered) {
+ /* XXX: Instead send presigned redirect or read-through */
+ op_ret = -ERR_INVALID_OBJECT_STATE;
+ } else { // fetch object for sync and set cloud_tier attrs
+ bufferlist t, t_tier;
+ RGWObjTier tier_config;
+ m.get_tier_config(&tier_config);
+
+ t.append("cloud-s3");
+ attrs[RGW_ATTR_CLOUD_TIER_TYPE] = t;
+ encode(tier_config, t_tier);
+ attrs[RGW_ATTR_CLOUD_TIER_CONFIG] = t_tier;
+ }
+ }
+ } catch (const buffer::end_of_buffer&) {
+ // ignore empty manifest; it's not cloud-tiered
+ } catch (const std::exception& e) {
+ }
+ }
+
+ return op_ret;
+}
+
void rgw_bucket_object_pre_exec(req_state *s)
{
if (s->expect_cont)
filter = &*decompress;
}
- attr_iter = attrs.find(RGW_ATTR_MANIFEST);
- if (attr_iter != attrs.end() && get_type() == RGW_OP_GET_OBJ && get_data) {
- RGWObjManifest m;
- try {
- decode(m, attr_iter->second);
- if (m.get_tier_type() == "cloud-s3" && !sync_cloudtiered) {
- /* XXX: Instead send presigned redirect or read-through */
- op_ret = -ERR_INVALID_OBJECT_STATE;
+ if (get_type() == RGW_OP_GET_OBJ && get_data) {
+ op_ret = handle_cloudtier_obj(attrs, sync_cloudtiered);
+ if (op_ret < 0) {
+ ldpp_dout(this, 4) << "Cannot get cloud tiered object: " << *s->object
+ <<". Failing with " << op_ret << dendl;
+ if (op_ret == -ERR_INVALID_OBJECT_STATE) {
s->err.message = "This object was transitioned to cloud-s3";
- ldpp_dout(this, 4) << "Cannot get cloud tiered object. Failing with "
- << op_ret << dendl;
- goto done_err;
}
- } catch (const buffer::end_of_buffer&) {
- // ignore empty manifest; it's not cloud-tiered
- } catch (const std::exception& e) {
- ldpp_dout(this, 1) << "WARNING: failed to decode object manifest for "
- << *s->object << ": " << e.what() << dendl;
+ goto done_err;
}
}