mys3cmd rb --recursive s3://$d_bkt
mys3cmd rb --recursive s3://$o_bkt
+############################################################
+# copy a multipart object to itself
+# run gc process after the copy, then try to get the object
+
+o_bkt="orig-mp-bkt-8"
+
+mys3cmd mb s3://$o_bkt
+
+mp_obj="multipart-obj-1"
+mys3cmd put -q $huge_obj s3://${o_bkt}/$mp_obj
+
+mys3cmd cp --mime-type="text/plain" s3://${o_bkt}/$mp_obj s3://${o_bkt}/$mp_obj
+
+#####################################################################
+# FORCE GARBAGE COLLECTION
+sleep 6 # since for testing age at which gc can happen is 5 secs
+radosgw-admin gc process --include-all
+#####################################################################
+
+mp_obj_retrieved="multipart-obj-1-retrieved"
+mys3cmd get s3://${o_bkt}/$mp_obj $mp_obj_retrieved --force
+
+if [ -f $mp_obj_retrieved ]; then
+ rm -f $mp_obj_retrieved
+else
+ echo "ERROR: failed to get the object after copying to itself"
+ exit 1
+fi
+
+mys3cmd rb --recursive s3://$o_bkt
+
#####################################################################
# FORCE GARBAGE COLLECTION
sleep 6 # since for testing age at which gc can happen is 5 secs
int RGWRados::Object::Write::_do_write_meta(const DoutPrefixProvider *dpp,
uint64_t size, uint64_t accounted_size,
map<string, bufferlist>& attrs,
- bool assume_noent, bool modify_tail,
- void *_index_op, optional_yield y,
- bool log_op)
+ bool assume_noent, void *_index_op,
+ optional_yield y, bool log_op)
{
RGWRados::Bucket::UpdateIndex *index_op = static_cast<RGWRados::Bucket::UpdateIndex *>(_index_op);
RGWRados *store = target->get_store();
if (!ptag && !index_op->get_optag()->empty()) {
ptag = index_op->get_optag();
}
- r = target->prepare_atomic_modification(dpp, op, reset_obj, ptag, meta.if_match, meta.if_nomatch, false, modify_tail, y);
+ r = target->prepare_atomic_modification(dpp, op, reset_obj, ptag, meta.if_match, meta.if_nomatch, false, meta.modify_tail, y);
if (r < 0)
return r;
poolid = ioctx.get_id();
- r = target->complete_atomic_modification(dpp);
+ r = target->complete_atomic_modification(dpp, meta.keep_tail);
if (r < 0) {
ldpp_dout(dpp, 0) << "ERROR: complete_atomic_modification returned r=" << r << dendl;
}
bool assume_noent = (meta.if_match == NULL && meta.if_nomatch == NULL);
int r;
if (assume_noent) {
- r = _do_write_meta(dpp, size, accounted_size, attrs, assume_noent, meta.modify_tail, (void *)&index_op, y, log_op);
+ r = _do_write_meta(dpp, size, accounted_size, attrs, assume_noent, (void *)&index_op, y, log_op);
if (r == -EEXIST) {
assume_noent = false;
}
}
if (!assume_noent) {
- r = _do_write_meta(dpp, size, accounted_size, attrs, assume_noent, meta.modify_tail, (void *)&index_op, y, log_op);
+ r = _do_write_meta(dpp, size, accounted_size, attrs, assume_noent, (void *)&index_op, y, log_op);
}
return r;
}
write_op.meta.olh_epoch = olh_epoch;
write_op.meta.delete_at = delete_at;
write_op.meta.modify_tail = !copy_itself;
+ write_op.meta.keep_tail = copy_itself;
ret = write_op.write_meta(dpp, obj_size, astate->accounted_size, attrs, y);
if (ret < 0) {
return 0;
}
-int RGWRados::Object::complete_atomic_modification(const DoutPrefixProvider *dpp)
+int RGWRados::Object::complete_atomic_modification(const DoutPrefixProvider *dpp, bool keep_tail)
{
- if ((!manifest)|| state->keep_tail)
+ if ((!manifest) || state->keep_tail || keep_tail)
return 0;
cls_rgw_obj_chain chain;
}
r = index_op.complete_del(dpp, poolid, epoch, state->mtime, params.remove_objs, y, log_op);
- int ret = target->complete_atomic_modification(dpp);
+ int ret = target->complete_atomic_modification(dpp, false);
if (ret < 0) {
ldpp_dout(dpp, 0) << "ERROR: complete_atomic_modification returned ret=" << ret << dendl;
}
int prepare_atomic_modification(const DoutPrefixProvider *dpp, librados::ObjectWriteOperation& op, bool reset_obj, const std::string *ptag,
const char *ifmatch, const char *ifnomatch, bool removal_op, bool modify_tail, optional_yield y);
- int complete_atomic_modification(const DoutPrefixProvider *dpp);
+ int complete_atomic_modification(const DoutPrefixProvider *dpp, bool keep_tail);
public:
Object(RGWRados *_store, const RGWBucketInfo& _bucket_info, RGWObjectCtx& _ctx, const rgw_obj& _obj) : store(_store), bucket_info(_bucket_info),
const std::string *user_data;
rgw_zone_set *zones_trace;
bool modify_tail;
+ bool keep_tail;
bool completeMultipart;
bool appendable;
MetaParams() : mtime(NULL), rmattrs(NULL), data(NULL), manifest(NULL), ptag(NULL),
remove_objs(NULL), category(RGWObjCategory::Main), flags(0),
if_match(NULL), if_nomatch(NULL), canceled(false), user_data(nullptr), zones_trace(nullptr),
- modify_tail(false), completeMultipart(false), appendable(false) {}
+ modify_tail(false), keep_tail(false), completeMultipart(false), appendable(false) {}
} meta;
explicit Write(RGWRados::Object *_target) : target(_target) {}
int _do_write_meta(const DoutPrefixProvider *dpp,
uint64_t size, uint64_t accounted_size,
std::map<std::string, bufferlist>& attrs,
- bool modify_tail, bool assume_noent,
- void *index_op, optional_yield y,
- bool log_op = true);
+ bool assume_noent, void *index_op,
+ optional_yield y, bool log_op = true);
int write_meta(const DoutPrefixProvider *dpp, uint64_t size, uint64_t accounted_size,
std::map<std::string, bufferlist>& attrs, optional_yield y, bool log_op = true);
int write_data(const char *data, uint64_t ofs, uint64_t len, bool exclusive);