virtual bool filter(string& name, string& key) = 0;
};
+struct RGWCloneRangeInfo {
+ rgw_obj src;
+ off_t src_ofs;
+ off_t dst_ofs;
+ size_t len;
+};
+
/**
* Abstract class defining the interface for storage devices used by RGW.
*/
size_t size) = 0;
virtual int clone_obj(rgw_obj& dst_obj, off_t dst_ofs,
- rgw_obj& src_obj, off_t src_ofs,
- size_t size,
+ rgw_obj& src_obj, off_t src_ofs,
+ size_t size, map<string, bufferlist> attrs) {
+ RGWCloneRangeInfo info;
+ vector<RGWCloneRangeInfo> v;
+ info.src = src_obj;
+ info.src_ofs = src_ofs;
+ info.len = size;
+ v.push_back(info);
+ return clone_objs(dst_obj, v, attrs);
+ }
+
+ virtual int clone_objs(rgw_obj& dst_obj,
+ vector<RGWCloneRangeInfo>& ranges,
map<string, bufferlist> attrs) { return -ENOTSUP; }
/**
* a simple object read without keeping state
strcasecmp(s, "1") == 0);
}
+static inline void append_rand_alpha(string& src, string& dest, int len)
+{
+ dest = src;
+ char buf[len + 1];
+ gen_rand_alphanumeric(buf, len);
+ dest.append("_");
+ dest.append(buf);
+}
+
/** */
extern int parse_time(const char *time_str, time_t *time);
/** Check if a user has a permission on that ACL */
rgw_obj meta_obj;
rgw_obj target_obj;
RGWMPObj mp;
+ vector<RGWCloneRangeInfo> ranges;
ret = get_params();
ret = rgwstore->put_obj_meta(s->user.user_id, target_obj, NULL, attrs, false);
if (ret < 0)
goto done;
-
+
for (obj_iter = obj_parts.begin(); obj_iter != obj_parts.end(); ++obj_iter) {
string oid = mp.get_part(obj_iter->second.num);
rgw_obj src_obj(s->bucket_str, oid, s->object_str, mp_ns);
- ret = rgwstore->clone_range(target_obj, ofs, src_obj, 0, obj_iter->second.size);
- if (ret < 0)
- goto done;
+
+ RGWCloneRangeInfo range;
+ range.src = src_obj;
+ range.src_ofs = 0;
+ range.dst_ofs = ofs;
+ range.len = obj_iter->second.size;
+ ranges.push_back(range);
+
ofs += obj_iter->second.size;
}
+ ret = rgwstore->clone_objs(target_obj, ranges, attrs);
+ if (ret < 0)
+ goto done;
// now erase all parts
for (obj_iter = obj_parts.begin(); obj_iter != obj_parts.end(); ++obj_iter) {
size_t total_len;
time_t lastmod;
map<string, bufferlist>::iterator iter;
+ rgw_obj tmp_obj = dest_obj;
+ string tmp_oid;
+
+ append_rand_alpha(dest_obj.key, tmp_oid, 32);
+ tmp_obj.set_key(tmp_oid);
+
+ rgw_obj tmp_dest;
RGW_LOG(5) << "Copy object " << src_obj.bucket << ":" << src_obj.object << " => " << dest_obj.bucket << ":" << dest_obj.object << dendl;
// In the first call to put_obj_data, we pass ofs == -1 so that it will do
// a write_full, wiping out whatever was in the object before this
- r = put_obj_data(id, dest_obj, data, ((ofs == 0) ? -1 : ofs), ret);
+ r = put_obj_data(id, tmp_obj, data, ((ofs == 0) ? -1 : ofs), ret);
free(data);
if (r < 0)
goto done_err;
}
attrs = attrset;
- ret = put_obj_meta(id, dest_obj, mtime, attrs, false);
+ ret = clone_obj(dest_obj, 0, tmp_obj, 0, end, attrs);
+ if (mtime)
+ obj_stat(tmp_obj, NULL, mtime);
+
+ r = rgwstore->delete_obj(id, tmp_obj);
+ if (r < 0)
+ RGW_LOG(0) << "ERROR: could not remove " << tmp_obj << dendl;
finish_get_obj(&handle);
return ret;
done_err:
+ rgwstore->delete_obj(id, tmp_obj);
finish_get_obj(&handle);
return r;
}
return io_ctx.clone_range(dst_oid, dst_ofs, src_oid, src_ofs, size);
}
-int RGWRados::clone_obj(rgw_obj& dst_obj, off_t dst_ofs,
- rgw_obj& src_obj, off_t src_ofs, size_t size,
+int RGWRados::clone_objs(rgw_obj& dst_obj,
+ vector<RGWCloneRangeInfo>& ranges,
map<string, bufferlist> attrs)
{
std::string& bucket = dst_obj.bucket;
std::string& dst_oid = dst_obj.object;
- std::string& src_oid = src_obj.object;
librados::IoCtx io_ctx;
int r = open_bucket_ctx(bucket, io_ctx);
bufferlist& bl = iter->second;
op.setxattr(name.c_str(), bl);
}
- op.clone_range(dst_ofs, src_oid, src_ofs, size);
+ vector<RGWCloneRangeInfo>::iterator range_iter;
+ for (range_iter = ranges.begin(); range_iter != ranges.end(); ++range_iter) {
+ RGWCloneRangeInfo& range = *range_iter;
+ op.clone_range(range.dst_ofs, range.src.object, range.src_ofs, range.len);
+ }
bufferlist outbl;
int ret = io_ctx.operate(dst_oid, &op, &outbl);
virtual bool aio_completed(void *handle);
virtual int clone_range(rgw_obj& dst_obj, off_t dst_ofs,
rgw_obj& src_obj, off_t src_ofs, size_t size);
- virtual int clone_obj(rgw_obj& dst_obj, off_t dst_ofs,
- rgw_obj& src_obj, off_t src_ofs, size_t size,
+ virtual int clone_objs(rgw_obj& dst_obj,
+ vector<RGWCloneRangeInfo>& ranges,
map<string, bufferlist> attrs);
/** Copy an object, with many extra options */