return 0;
}
- void *obj_ctx = rgwstore->create_context(s);
+
+int RGWGetObj::read_user_manifest_part(rgw_bucket& bucket, RGWObjEnt& ent, RGWAccessControlPolicy *bucket_policy, off_t start_ofs, off_t end_ofs)
+{
+ ldout(s->cct, 0) << "user manifest obj=" << ent.name << dendl;
+
+ void *handle = NULL;
+ off_t cur_ofs = start_ofs;
+ off_t cur_end = end_ofs;
+ utime_t start_time = s->time;
+
+ rgw_obj part(bucket, ent.name);
+
+ map<string, bufferlist> attrs;
+
+ uint64_t obj_size, read_size;
- rgwstore->set_atomic(obj_ctx, part);
- rgwstore->set_prefetch_data(obj_ctx, part);
- ret = rgwstore->prepare_get_obj(obj_ctx, part, &cur_ofs, &cur_end, &attrs, NULL,
++ void *obj_ctx = store->create_context(s);
+ RGWAccessControlPolicy obj_policy(s->cct);
+
+ ldout(s->cct, 20) << "reading obj=" << part << " ofs=" << cur_ofs << " end=" << cur_end << dendl;
+
- ret = rgwstore->get_obj(obj_ctx, &handle, part, bl, cur_ofs, cur_end);
++ store->set_atomic(obj_ctx, part);
++ store->set_prefetch_data(obj_ctx, part);
++ ret = store->prepare_get_obj(obj_ctx, part, &cur_ofs, &cur_end, &attrs, NULL,
+ NULL, NULL, NULL, NULL, NULL, &obj_size, &handle, &s->err);
+ if (ret < 0)
+ goto done_err;
+
+ if (obj_size != ent.size) {
+ // hmm.. something wrong, object not as expected, abort!
+ ldout(s->cct, 0) << "ERROR: expected read size=" << read_size << ", actual read size=" << ent.size << dendl;
+ ret = -EIO;
+ goto done_err;
+ }
+
+ ret = policy_from_attrset(s->cct, attrs, &obj_policy);
+ if (ret < 0)
+ goto done_err;
+
+ if (!verify_object_permission(s, bucket_policy, &obj_policy, RGW_PERM_READ)) {
+ ret = -EPERM;
+ goto done_err;
+ }
+
+ perfcounter->inc(l_rgw_get_b, cur_end - cur_ofs);
+ while (cur_ofs <= cur_end) {
+ bufferlist bl;
+ read_size = cur_end - cur_ofs + 1;
- rgwstore->destroy_context(obj_ctx);
++ ret = store->get_obj(obj_ctx, &handle, part, bl, cur_ofs, cur_end);
+ if (ret < 0)
+ goto done_err;
+
+ len = bl.length();
+ cur_ofs += len;
+ ofs += len;
+ ret = 0;
+ perfcounter->finc(l_rgw_get_lat,
+ (ceph_clock_now(s->cct) - start_time));
+ send_response(bl);
+
+ start_time = ceph_clock_now(s->cct);
+ }
+
- rgwstore->finish_get_obj(&handle);
++ store->destroy_context(obj_ctx);
+ obj_ctx = NULL;
+
- rgwstore->destroy_context(obj_ctx);
++ store->finish_get_obj(&handle);
+
+ return 0;
+
+done_err:
+ if (obj_ctx)
- int r = rgwstore->list_objects(bucket, MAX_LIST_OBJS, obj_prefix, delim, marker,
- objs, common_prefixes,
- true, no_ns, &is_truncated, NULL);
++ store->destroy_context(obj_ctx);
+ return ret;
+}
+
+int RGWGetObj::iterate_user_manifest_parts(rgw_bucket& bucket, string& obj_prefix, RGWAccessControlPolicy *bucket_policy,
+ uint64_t *ptotal_len, bool read_data)
+{
+ uint64_t obj_ofs = 0, len_count = 0;
+ bool found_start = false, found_end = false;
+ string delim;
+ string marker;
+ bool is_truncated;
+ string no_ns;
+ map<string, bool> common_prefixes;
+ vector<RGWObjEnt> objs;
+
+ utime_t start_time = ceph_clock_now(s->cct);
+
+ do {
+#define MAX_LIST_OBJS 100
- int r = rgwstore->get_bucket_info(NULL, bucket_name, bucket_info);
++ int r = store->list_objects(bucket, MAX_LIST_OBJS, obj_prefix, delim, marker,
++ objs, common_prefixes,
++ true, no_ns, &is_truncated, NULL);
+ if (r < 0)
+ return r;
+
+ vector<RGWObjEnt>::iterator viter;
+
+ for (viter = objs.begin(); viter != objs.end() && !found_end; ++viter) {
+ RGWObjEnt& ent = *viter;
+ uint64_t cur_total_len = obj_ofs;
+ uint64_t start_ofs = 0, end_ofs = ent.size;
+
+ if (!found_start && cur_total_len + ent.size > (uint64_t)ofs) {
+ start_ofs = ofs - obj_ofs;
+ found_start = true;
+ }
+
+ obj_ofs += ent.size;
+
+ if (!found_end && obj_ofs > (uint64_t)end) {
+ end_ofs = end - cur_total_len + 1;
+ found_end = true;
+ }
+
+ perfcounter->finc(l_rgw_get_lat,
+ (ceph_clock_now(s->cct) - start_time));
+
+ if (found_start) {
+ len_count += end_ofs - start_ofs;
+
+ if (read_data) {
+ r = read_user_manifest_part(bucket, ent, bucket_policy, start_ofs, end_ofs);
+ if (r < 0)
+ return r;
+ }
+ }
+ marker = ent.name;
+
+ start_time = ceph_clock_now(s->cct);
+ }
+ } while (is_truncated && !found_end);
+
+ if (ptotal_len)
+ *ptotal_len = len_count;
+
+ return 0;
+}
+
+int RGWGetObj::handle_user_manifest(const char *prefix)
+{
+ ldout(s->cct, 2) << "RGWGetObj::handle_user_manifest() prefix=" << prefix << dendl;
+
+ string prefix_str = prefix;
+ int pos = prefix_str.find('/');
+ if (pos < 0)
+ return -EINVAL;
+
+ string bucket_name = prefix_str.substr(0, pos);
+ string obj_prefix = prefix_str.substr(pos + 1);
+
+ rgw_bucket bucket;
+
+ RGWAccessControlPolicy _bucket_policy(s->cct);
+ RGWAccessControlPolicy *bucket_policy;
+
+ if (bucket_name.compare(s->bucket.name) != 0) {
+ RGWBucketInfo bucket_info;
- r = read_policy(s, bucket_info, bucket_policy, bucket, no_obj);
++ int r = store->get_bucket_info(NULL, bucket_name, bucket_info);
+ if (r < 0) {
+ ldout(s->cct, 0) << "could not get bucket info for bucket=" << bucket_name << dendl;
+ return r;
+ }
+ bucket = bucket_info.bucket;
+ string no_obj;
+ bucket_policy = &_bucket_policy;
++ r = read_policy(store, s, bucket_info, bucket_policy, bucket, no_obj);
+ if (r < 0) {
+ ldout(s->cct, 0) << "failed to read bucket policy" << dendl;
+ return r;
+ }
+ } else {
+ bucket = s->bucket;
+ bucket_policy = s->bucket_acl;
+ }
+
+ /* dry run to find out total length */
+ int r = iterate_user_manifest_parts(bucket, obj_prefix, bucket_policy, &total_len, false);
+ if (r < 0)
+ return r;
+
+ s->obj_size = total_len;
+
+ r = iterate_user_manifest_parts(bucket, obj_prefix, bucket_policy, NULL, true);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
void RGWGetObj::execute()
{
void *handle = NULL;
if (ret < 0)
goto done;
- ret = store->prepare_get_obj(s->obj_ctx, obj, &ofs, &end, &attrs, mod_ptr,
- unmod_ptr, &lastmod, if_match, if_nomatch, &total_len, &s->obj_size, &handle, &s->err);
+ new_ofs = ofs;
+ new_end = end;
+
- ret = rgwstore->prepare_get_obj(s->obj_ctx, obj, &new_ofs, &new_end, &attrs, mod_ptr,
- unmod_ptr, &lastmod, if_match, if_nomatch, &total_len, &s->obj_size, &handle, &s->err);
++ ret = store->prepare_get_obj(s->obj_ctx, obj, &new_ofs, &new_end, &attrs, mod_ptr,
++ unmod_ptr, &lastmod, if_match, if_nomatch, &total_len, &s->obj_size, &handle, &s->err);
if (ret < 0)
goto done;
int RGWPutObjProcessor_Plain::complete(string& etag, map<string, bufferlist>& attrs)
{
- int r = rgwstore->put_obj_meta(s->obj_ctx, obj, data.length(), NULL, attrs,
- RGW_OBJ_CATEGORY_MAIN, false, NULL, &data, NULL, NULL);
+ int r = store->put_obj_meta(s->obj_ctx, obj, data.length(), NULL, attrs,
- RGW_OBJ_CATEGORY_MAIN, false, NULL, &data, NULL);
++ RGW_OBJ_CATEGORY_MAIN, false, NULL, &data, NULL, NULL);
return r;
}
manifest.obj_size = obj_len;
- rgwstore->set_atomic(s->obj_ctx, head_obj);
+ store->set_atomic(s->obj_ctx, head_obj);
- int r = rgwstore->put_obj_meta(s->obj_ctx, head_obj, obj_len, NULL, attrs,
- RGW_OBJ_CATEGORY_MAIN, false, NULL, &first_chunk, &manifest, NULL);
+ int r = store->put_obj_meta(s->obj_ctx, head_obj, obj_len, NULL, attrs,
- RGW_OBJ_CATEGORY_MAIN, false, NULL, &first_chunk, &manifest);
++ RGW_OBJ_CATEGORY_MAIN, false, NULL, &first_chunk, &manifest, NULL);
return r;
}
int RGWPutObjProcessor_Multipart::complete(string& etag, map<string, bufferlist>& attrs)
{
- int r = rgwstore->put_obj_meta(s->obj_ctx, obj, s->obj_size, NULL, attrs, RGW_OBJ_CATEGORY_MAIN, false, NULL, NULL, NULL, NULL);
- int r = store->put_obj_meta(s->obj_ctx, obj, s->obj_size, NULL, attrs, RGW_OBJ_CATEGORY_MAIN, false, NULL, NULL, NULL);
++ int r = store->put_obj_meta(s->obj_ctx, obj, s->obj_size, NULL, attrs, RGW_OBJ_CATEGORY_MAIN, false, NULL, NULL, NULL, NULL);
if (r < 0)
return r;
dest_bucket = dest_bucket_info.bucket;
- rgwstore->set_atomic(s->obj_ctx, src_obj);
- rgwstore->set_prefetch_data(s->obj_ctx, src_obj);
+ rgw_obj src_obj(src_bucket, src_object);
- rgwstore->set_atomic(s->obj_ctx, dest_obj);
++ store->set_atomic(s->obj_ctx, src_obj);
++ store->set_prefetch_data(s->obj_ctx, src_obj);
+
+ rgw_obj dest_obj(dest_bucket, dest_object);
++ store->set_atomic(s->obj_ctx, dest_obj);
+
/* check source object permissions */
- ret = read_policy(s, src_bucket_info, &src_policy, src_bucket, src_object);
+ ret = read_policy(store, s, src_bucket_info, &src_policy, src_bucket, src_object);
if (ret < 0)
return ret;
obj.init_ns(s->bucket, tmp_obj_name, mp_ns);
// the meta object will be indexed with 0 size, we c
- ret = rgwstore->put_obj_meta(s->obj_ctx, obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MULTIMETA, true, NULL, NULL, NULL, NULL);
- ret = store->put_obj_meta(s->obj_ctx, obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MULTIMETA, true, NULL, NULL, NULL);
++ ret = store->put_obj_meta(s->obj_ctx, obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MULTIMETA, true, NULL, NULL, NULL, NULL);
} while (ret == -EEXIST);
done:
send_response();
attrs[RGW_ATTR_ETAG] = etag_bl;
target_obj.init(s->bucket, s->object_str);
- rgwstore->set_atomic(s->obj_ctx, target_obj);
- ret = rgwstore->put_obj_meta(s->obj_ctx, target_obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MAIN, false, NULL, NULL, NULL, NULL);
+ store->set_atomic(s->obj_ctx, target_obj);
- ret = store->put_obj_meta(s->obj_ctx, target_obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MAIN, false, NULL, NULL, NULL);
++ ret = store->put_obj_meta(s->obj_ctx, target_obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MAIN, false, NULL, NULL, NULL, NULL);
if (ret < 0)
goto done;
manifest.obj_size = ofs;
- rgwstore->set_atomic(s->obj_ctx, target_obj);
+ store->set_atomic(s->obj_ctx, target_obj);
- ret = rgwstore->put_obj_meta(s->obj_ctx, target_obj, ofs, NULL, attrs,
- RGW_OBJ_CATEGORY_MAIN, false, NULL, NULL, &manifest, NULL);
+ ret = store->put_obj_meta(s->obj_ctx, target_obj, ofs, NULL, attrs,
- RGW_OBJ_CATEGORY_MAIN, false, NULL, NULL, &manifest);
++ RGW_OBJ_CATEGORY_MAIN, false, NULL, NULL, &manifest, NULL);
if (ret < 0)
goto done;
if (ret < 0)
return ret;
- ret = rgwstore->put_obj_meta(ctx, dest_obj, end + 1, NULL, attrset, category, false, NULL, &first_chunk, &manifest, &tag);
+ if (replace_attrs) {
+ attrset = attrs;
+ }
+
+ RGWObjManifest manifest;
+ RGWObjState *astate = NULL;
+ RGWRadosCtx *rctx = (RGWRadosCtx *)ctx;
+ ret = get_obj_state(rctx, src_obj, &astate);
+ if (ret < 0)
+ return ret;
+
+ vector<rgw_obj> ref_objs;
+
+ bool copy_data = !astate->has_manifest;
+ bool copy_first = false;
+ if (astate->has_manifest) {
+ if (astate->manifest.objs.size() < 2) {
+ copy_data = true;
+ } else {
+ map<uint64_t, RGWObjManifestPart>::iterator iter = astate->manifest.objs.begin();
+ RGWObjManifestPart part = iter->second;
+ if (part.loc == src_obj) {
+ if (part.size > RGW_MAX_CHUNK_SIZE) // should never happen
+ copy_data = true;
+ else
+ copy_first = true;
+ }
+ }
+ }
+
+ if (copy_data) { /* refcounting tail wouldn't work here, just copy the data */
+ return copy_obj_data(ctx, handle, end, dest_obj, src_obj, mtime, attrset, category, err);
+ }
+
+ map<uint64_t, RGWObjManifestPart>::iterator miter = astate->manifest.objs.begin();
+
+ if (copy_first) // we need to copy first chunk, not increase refcount
+ ++miter;
+
+ RGWObjManifestPart *first_part = &miter->second;
+ string oid, key;
+ rgw_bucket bucket;
+ get_obj_bucket_and_oid_key(first_part->loc, bucket, oid, key);
+ librados::IoCtx io_ctx;
+
+ ret = open_bucket_ctx(bucket, io_ctx);
+ if (ret < 0)
+ return ret;
+
+ bufferlist first_chunk;
+
+ string tag;
+ append_rand_alpha(cct, tag, tag, 32);
+
+ for (; miter != astate->manifest.objs.end(); ++miter) {
+ RGWObjManifestPart& part = miter->second;
+ ObjectWriteOperation op;
+ manifest.objs[miter->first] = part;
+ cls_refcount_get(op, tag, true);
+
+ get_obj_bucket_and_oid_key(part.loc, bucket, oid, key);
+ io_ctx.locator_set_key(key);
+
+ ret = io_ctx.operate(oid, &op);
+ if (ret < 0)
+ goto done_ret;
+
+ ref_objs.push_back(part.loc);
+ }
+
+ if (copy_first) {
+ ret = get_obj(ctx, &handle, src_obj, first_chunk, 0, RGW_MAX_CHUNK_SIZE);
+ if (ret < 0)
+ goto done_ret;
+
+ first_part = &manifest.objs[0];
+ first_part->loc = dest_obj;
+ first_part->loc_ofs = 0;
+ first_part->size = first_chunk.length();
+ }
+
+ manifest.obj_size = total_len;
+
++ ret = put_obj_meta(ctx, dest_obj, end + 1, NULL, attrset, category, false, NULL, &first_chunk, &manifest, &tag);
+ if (mtime)
+ obj_stat(ctx, dest_obj, NULL, mtime, NULL, NULL);
+
+ return 0;
+
+done_ret:
+ vector<rgw_obj>::iterator riter;
+
+ /* rollback reference */
+ for (riter = ref_objs.begin(); riter != ref_objs.end(); ++riter) {
+ ObjectWriteOperation op;
+ cls_refcount_put(op, tag, true);
+
+ get_obj_bucket_and_oid_key(*riter, bucket, oid, key);
+ io_ctx.locator_set_key(key);
+
+ int r = io_ctx.operate(oid, &op);
+ if (r < 0) {
+ ldout(cct, 0) << "ERROR: cleanup after error failed to drop reference on obj=" << *riter << dendl;
+ }
+ }
+ return ret;
+}
+
+
+int RGWRados::copy_obj_data(void *ctx,
+ void *handle, off_t end,
+ rgw_obj& dest_obj,
+ rgw_obj& src_obj,
+ time_t *mtime,
+ map<string, bufferlist>& attrs,
+ RGWObjCategory category,
+ struct rgw_err *err)
+{
bufferlist first_chunk;
RGWObjManifest manifest;
RGWObjManifestPart *first_part;
}
manifest.obj_size = ofs;
- ret = rgwstore->put_obj_meta(ctx, dest_obj, end + 1, NULL, attrs, category, false, NULL, &first_chunk, &manifest, NULL);
- if (replace_attrs) {
- attrset = attrs;
- }
-
- ret = put_obj_meta(ctx, dest_obj, end + 1, NULL, attrset, category, false, NULL, &first_chunk, &manifest);
++ ret = put_obj_meta(ctx, dest_obj, end + 1, NULL, attrs, category, false, NULL, &first_chunk, &manifest, NULL);
if (mtime)
obj_stat(ctx, dest_obj, NULL, mtime, NULL, NULL);
return ret;
done_err:
- rgwstore->delete_obj(ctx, shadow_obj);
- delete_obj(ctx, shadow_obj, false);
++ delete_obj(ctx, shadow_obj);
finish_get_obj(&handle);
return r;
}
}
} while (is_truncated);
- rgw_obj obj(rgw_root_bucket, bucket.name);
+ rgw_obj obj(params.domain_root, bucket.name);
- r = delete_obj(NULL, obj, true);
+ r = delete_obj(NULL, obj);
if (r < 0)
return r;
complete = false;
break;
}
- r = rgwstore->delete_obj(NULL, entry.obj);
- r = delete_obj(NULL, entry.obj, false);
++ r = delete_obj(NULL, entry.obj);
if (r < 0 && r != -ENOENT) {
cerr << "failed to remove obj: " << entry.obj << std::endl;
complete = false;