virtual void finish_get_obj(void **handle) = 0;
- /**
+ virtual int clone_range(std::string& bucket, std::string& dst_oid, off_t dst_ofs,
+ std::string& src_oid, off_t src_ofs, size_t size, std::string& loc) = 0;
+ /**
* a simple object read without keeping state
*/
virtual int read(std::string& bucket, std::string& oid, off_t ofs, size_t size, bufferlist& bl) = 0;
#define ERR_INVALID_DIGEST 2004
#define ERR_BAD_DIGEST 2005
#define ERR_UNRESOLVABLE_EMAIL 2006
+#define ERR_INVALID_PART 2007
+#define ERR_INVALID_PART_ORDER 2008
+#define ERR_NO_SUCH_UPLOAD 2009
typedef void *RGWAccessHandle;
map<std::string, bufferlist>& attrs, bool exclusive);
int put_obj_data(std::string& id, std::string& bucket, std::string& obj, std::string& loc, const char *data,
off_t ofs, size_t size, time_t *mtime);
+ int clone_range(std::string& bucket, std::string& dst_oid, off_t dst_ofs,
+ std::string& src_oid, off_t src_ofs, size_t size, std::string& loc) { return -ENOTSUP; }
int copy_obj(std::string& id, std::string& dest_bucket, std::string& dest_obj,
std::string& src_bucket, std::string& src_obj,
time_t *mtime,
RGWMultiXMLParser parser;
string obj = s->object_str;
map<uint32_t, RGWUploadPartInfo> obj_parts;
+ map<uint32_t, RGWUploadPartInfo>::iterator obj_iter;
RGWAccessControlPolicy policy;
+ off_t ofs = 0;
+ string prefix;
ret = get_params();
if (ret < 0)
goto done;
}
- for (iter = parts->parts.begin(); iter != parts->parts.end(); ++iter) {
- RGW_LOG(0) << "part: " << iter->first << " etag: " << iter->second << dendl;
- }
-
obj.append(".");
+ prefix = obj;
obj.append(upload_id);
ret = get_multiparts_info(s, obj, obj_parts, policy);
+ if (ret == -ENOENT)
+ ret = -ERR_NO_SUCH_UPLOAD;
if (ret < 0)
goto done;
+ for (iter = parts->parts.begin(), obj_iter = obj_parts.begin();
+ iter != parts->parts.end();
+ ++iter, ++obj_iter) {
+ if (iter->first != (int)obj_iter->first) {
+ RGW_LOG(0) << "parts num mismatch: next requested: " << iter->first << " next uploaded: " << obj_iter->first << dendl;
+ ret = -ERR_INVALID_PART;
+ goto done;
+ }
+ if (iter->second.compare(obj_iter->second.etag) != 0) {
+ RGW_LOG(0) << "part: " << iter->first << " etag: " << iter->second << dendl;
+ ret = -ERR_INVALID_PART;
+ goto done;
+ }
+ }
+
+ for (obj_iter = obj_parts.begin(); obj_iter != obj_parts.end(); ++obj_iter) {
+ obj = prefix;
+ char buf[16];
+ snprintf(buf, 16, "%d", obj_iter->second.num);
+ obj.append(buf);
+ rgwstore->clone_range(s->bucket_str, s->object_str, ofs, obj, 0, obj_iter->second.size, s->object_str);
+ }
+
done:
send_response();
}
return r;
}
+int RGWRados::clone_range(std::string& bucket, std::string& dst_oid, off_t dst_ofs,
+ std::string& src_oid, off_t src_ofs, size_t size, std::string& loc)
+{
+ librados::IoCtx io_ctx;
+
+ int r = open_bucket_ctx(bucket, io_ctx);
+ if (r < 0)
+ return r;
+
+ io_ctx.locator_set_key(loc);
+
+ return io_ctx.clone_range(dst_oid, dst_ofs, src_oid, src_ofs, size);
+}
+
+
int RGWRados::get_obj(void **handle,
std::string& bucket, std::string& oid, string& loc,
char **data, off_t ofs, off_t end)
map<std::string, bufferlist>& attrs, bool exclusive);
virtual int put_obj_data(std::string& id, std::string& bucket, std::string& obj, std::string& loc, const char *data,
off_t ofs, size_t len, time_t *mtime);
+ virtual int clone_range(std::string& bucket, std::string& dst_oid, off_t dst_ofs,
+ std::string& src_oid, off_t src_ofs, size_t size, std::string& loc);
/** Copy an object, with many extra options */
virtual int copy_obj(std::string& id, std::string& dest_bucket, std::string& dest_obj,
std::string& src_bucket, std::string& src_obj,
{ ERR_INVALID_BUCKET_NAME, 400, "InvalidBucketName" },
{ ERR_INVALID_OBJECT_NAME, 400, "InvalidObjectName" },
{ ERR_UNRESOLVABLE_EMAIL, 400, "UnresolvableGrantByEmailAddress" },
+ { ERR_INVALID_PART, 400, "InvalidPart" },
+ { ERR_INVALID_PART_ORDER, 400, "InvalidPartOrder" },
{ EACCES, 403, "AccessDenied" },
{ EPERM, 403, "AccessDenied" },
{ ENOENT, 404, "NoSuchKey" },
{ ERR_NO_SUCH_BUCKET, 404, "NoSuchBucket" },
+ { ERR_NO_SUCH_UPLOAD, 404, "NoSuchUpload" },
{ ERR_METHOD_NOT_ALLOWED, 405, "MethodNotAllowed" },
{ ETIMEDOUT, 408, "RequestTimeout" },
{ EEXIST, 409, "BucketAlreadyExists" },