return rc;
}
+static void unaccount_entry(struct rgw_bucket_dir_header& header, struct rgw_bucket_dir_entry& entry)
+{
+ struct rgw_bucket_category_stats& stats = header.stats[entry.meta.category];
+ stats.num_entries--;
+ stats.total_size -= entry.meta.size;
+ stats.total_size_rounded -= get_rounded_size(entry.meta.size);
+}
+
+static int read_index_entry(cls_method_context_t hctx, string& name, struct rgw_bucket_dir_entry *entry)
+{
+ bufferlist current_entry;
+ int rc = cls_cxx_map_get_val(hctx, name, ¤t_entry);
+ if (rc < 0) {
+ return rc;
+ }
+
+ bufferlist::iterator cur_iter = current_entry.begin();
+ try {
+ ::decode(*entry, cur_iter);
+ } catch (buffer::error& err) {
+ CLS_LOG(1, "ERROR: read_index_entry(): failed to decode entry\n");
+ return -EIO;
+ }
+
+ CLS_LOG(1, "read_index_entry(): existing entry: epoch=%lld name=%s locator=%s\n", entry->epoch, entry->name.c_str(), entry->locator.c_str());
+ return 0;
+}
+
int rgw_bucket_complete_op(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
{
// decode request
return -EINVAL;
}
- bufferlist current_entry;
struct rgw_bucket_dir_entry entry;
bool ondisk = true;
- rc = cls_cxx_map_get_val(hctx, op.name, ¤t_entry);
- if (rc < 0) {
- if (rc != -ENOENT) {
- return rc;
- } else {
- rc = 0;
- entry.name = op.name;
- entry.epoch = op.epoch;
- entry.meta = op.meta;
- entry.locator = op.locator;
- ondisk = false;
- }
- } else {
- bufferlist::iterator cur_iter = current_entry.begin();
- try {
- ::decode(entry, cur_iter);
- CLS_LOG(1, "rgw_bucket_complete_op(): existing entry: epoch=%lld name=%s locator=%s\n", entry.epoch, entry.name.c_str(), entry.locator.c_str());
- } catch (buffer::error& err) {
- CLS_LOG(1, "ERROR: rgw_bucket_complete_op(): failed to decode entry\n");
- }
+
+ rc = read_index_entry(hctx, op.name, &entry);
+ if (rc == -ENOENT) {
+ entry.name = op.name;
+ entry.epoch = op.epoch;
+ entry.meta = op.meta;
+ entry.locator = op.locator;
+ ondisk = false;
+ } else if (rc < 0) {
+ return rc;
}
if (op.tag.size()) {
}
if (entry.exists) {
- struct rgw_bucket_category_stats& stats = header.stats[entry.meta.category];
- stats.num_entries--;
- stats.total_size -= entry.meta.size;
- stats.total_size_rounded -= get_rounded_size(entry.meta.size);
+ unaccount_entry(header, entry);
}
switch (op.op) {
break;
}
+ list<string>::iterator remove_iter;
+ CLS_LOG(0, "rgw_bucket_complete_op(): remove_objs.size()=%d\n", op.remove_objs.size());
+ for (remove_iter = op.remove_objs.begin(); remove_iter != op.remove_objs.end(); ++remove_iter) {
+ string& remove_oid_name = *remove_iter;
+ CLS_LOG(1, "rgw_bucket_complete_op(): removing entries, read_index_entry name=%s\n", remove_oid_name.c_str());
+ struct rgw_bucket_dir_entry remove_entry;
+ int ret = read_index_entry(hctx, remove_oid_name, &remove_entry);
+ if (ret < 0) {
+ CLS_LOG(1, "rgw_bucket_complete_op(): removing entries, read_index_entry name=%s ret=%d\n", remove_oid_name.c_str(), rc);
+ continue;
+ }
+ CLS_LOG(0, "rgw_bucket_complete_op(): entry.name=%s entry.meta.category=%d\n", remove_entry.name.c_str(), remove_entry.meta.category);
+ unaccount_entry(header, remove_entry);
+
+ ret = cls_cxx_map_remove_key(hctx, remove_oid_name);
+ if (ret < 0) {
+ CLS_LOG(1, "rgw_bucket_complete_op(): cls_cxx_map_remove_key, failed to remove entry, name=%s read_index_entry ret=%d\n", remove_oid_name.c_str(), rc);
+ continue;
+ }
+ }
+
bufferlist new_header_bl;
::encode(header, new_header_bl);
return cls_cxx_map_write_header(hctx, &new_header_bl);
}
void cls_rgw_bucket_complete_op(ObjectWriteOperation& o, uint8_t op, string& tag,
- uint64_t epoch, string& name, rgw_bucket_dir_entry_meta& dir_meta)
+ uint64_t epoch, string& name, rgw_bucket_dir_entry_meta& dir_meta,
+ list<string> *remove_objs)
{
bufferlist in;
call.name = name;
call.epoch = epoch;
call.meta = dir_meta;
+ if (remove_objs)
+ call.remove_objs = *remove_objs;
::encode(call, in);
o.exec("rgw", "bucket_complete_op", in);
}
string& name, string& locator);
void cls_rgw_bucket_complete_op(librados::ObjectWriteOperation& o, uint8_t op, string& tag,
- uint64_t epoch, string& name, rgw_bucket_dir_entry_meta& dir_meta);
+ uint64_t epoch, string& name, rgw_bucket_dir_entry_meta& dir_meta,
+ list<string> *remove_objs);
int cls_rgw_list_op(librados::IoCtx& io_ctx, string& oid, string& start_obj,
string& filter_prefix, uint32_t num_entries,
struct rgw_bucket_dir_entry_meta meta;
string tag;
+ list<string> remove_objs;
+
void encode(bufferlist &bl) const {
- ENCODE_START(3, 3, bl);
+ ENCODE_START(4, 3, bl);
::encode(op, bl);
::encode(name, bl);
::encode(epoch, bl);
::encode(meta, bl);
::encode(tag, bl);
::encode(locator, bl);
+ ::encode(remove_objs, bl);
ENCODE_FINISH(bl);
}
void decode(bufferlist::iterator &bl) {
- DECODE_START_LEGACY_COMPAT_LEN(3, 3, 3, bl);
+ DECODE_START_LEGACY_COMPAT_LEN(4, 3, 3, bl);
::decode(op, bl);
::decode(name, bl);
::decode(epoch, bl);
if (struct_v >= 2) {
::decode(locator, bl);
}
+ if (struct_v >= 4) {
+ ::decode(remove_objs, bl);
+ }
DECODE_FINISH(bl);
}
void dump(Formatter *f) const;
int put_obj_meta(void *ctx, rgw_obj& obj, uint64_t size, time_t *mtime,
map<std::string, bufferlist>& attrs, RGWObjCategory category, int flags,
map<std::string, bufferlist>* rmattrs, const bufferlist *data,
- RGWObjManifest *manifest, const string *ptag);
+ RGWObjManifest *manifest, const string *ptag, list<string> *remove_objs);
int put_obj_data(void *ctx, rgw_obj& obj, const char *data,
off_t ofs, size_t len, bool exclusive);
int RGWCache<T>::put_obj_meta(void *ctx, rgw_obj& obj, uint64_t size, time_t *mtime,
map<std::string, bufferlist>& attrs, RGWObjCategory category, int flags,
map<std::string, bufferlist>* rmattrs, const bufferlist *data,
- RGWObjManifest *manifest, const string *ptag)
+ RGWObjManifest *manifest, const string *ptag, list<string> *remove_objs)
{
rgw_bucket bucket;
string oid;
info.flags |= CACHE_FLAG_DATA;
}
}
- int ret = T::put_obj_meta(ctx, obj, size, mtime, attrs, category, flags, rmattrs, data, manifest, ptag);
+ int ret = T::put_obj_meta(ctx, obj, size, mtime, attrs, category, flags, rmattrs, data, manifest, ptag, remove_objs);
if (cacheable) {
string name = normal_name(bucket, oid);
if (ret >= 0) {
int RGWPutObjProcessor_Plain::do_complete(string& etag, map<string, bufferlist>& attrs)
{
int r = store->put_obj_meta(s->obj_ctx, obj, data.length(), NULL, attrs,
- RGW_OBJ_CATEGORY_MAIN, PUT_OBJ_CREATE, NULL, &data, NULL, NULL);
+ RGW_OBJ_CATEGORY_MAIN, PUT_OBJ_CREATE, NULL, &data, NULL, NULL, NULL);
return r;
}
store->set_atomic(s->obj_ctx, head_obj);
int r = store->put_obj_meta(s->obj_ctx, head_obj, obj_len, NULL, attrs,
- RGW_OBJ_CATEGORY_MAIN, PUT_OBJ_CREATE, NULL, &first_chunk, &manifest, NULL);
+ RGW_OBJ_CATEGORY_MAIN, PUT_OBJ_CREATE, NULL, &first_chunk, &manifest, NULL, NULL);
return r;
}
{
complete_parts();
- int r = store->put_obj_meta(s->obj_ctx, head_obj, s->obj_size, NULL, attrs, RGW_OBJ_CATEGORY_MAIN, 0, NULL, NULL, NULL, NULL);
+ int r = store->put_obj_meta(s->obj_ctx, head_obj, s->obj_size, NULL, attrs, RGW_OBJ_CATEGORY_MAIN, 0, NULL, NULL, NULL, NULL, NULL);
if (r < 0)
return r;
obj.init_ns(s->bucket, tmp_obj_name, mp_ns);
// the meta object will be indexed with 0 size, we c
- ret = store->put_obj_meta(s->obj_ctx, obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MULTIMETA, PUT_OBJ_CREATE_EXCL, NULL, NULL, NULL, NULL);
+ ret = store->put_obj_meta(s->obj_ctx, obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MULTIMETA, PUT_OBJ_CREATE_EXCL, NULL, NULL, NULL, NULL, NULL);
} while (ret == -EEXIST);
}
attrs[RGW_ATTR_ETAG] = etag_bl;
target_obj.init(s->bucket, s->object_str);
+
+ list<string> remove_objs; /* objects to be removed from index listing */
for (obj_iter = obj_parts.begin(); obj_iter != obj_parts.end(); ++obj_iter) {
RGWUploadPartInfo& obj_part = obj_iter->second;
+ string oid = mp.get_part(obj_iter->second.num);
+ rgw_obj src_obj;
+ src_obj.init_ns(s->bucket, oid, mp_ns);
if (obj_part.manifest.empty()) {
- string oid = mp.get_part(obj_iter->second.num);
- rgw_obj src_obj;
- src_obj.init_ns(s->bucket, oid, mp_ns);
-
RGWObjManifestPart& part = manifest.objs[ofs];
part.loc = src_obj;
manifest.append(obj_part.manifest);
}
+ remove_objs.push_back(src_obj.object);
+
ofs += obj_part.size;
}
store->set_atomic(s->obj_ctx, target_obj);
ret = store->put_obj_meta(s->obj_ctx, target_obj, ofs, NULL, attrs,
- RGW_OBJ_CATEGORY_MAIN, PUT_OBJ_CREATE, NULL, NULL, &manifest, NULL);
+ RGW_OBJ_CATEGORY_MAIN, PUT_OBJ_CREATE, NULL, NULL, &manifest, NULL, &remove_objs);
if (ret < 0)
return;
map<string, bufferlist>* rmattrs,
const bufferlist *data,
RGWObjManifest *manifest,
- const string *ptag)
+ const string *ptag,
+ list<string> *remove_objs)
{
rgw_bucket bucket;
std::string oid, key;
ut = ceph_clock_now(cct);
r = complete_update_index(bucket, obj.object, index_tag, epoch, size,
- ut, etag, content_type, &acl_bl, category);
+ ut, etag, content_type, &acl_bl, category, remove_objs);
if (r < 0)
goto done_cancel;
manifest.obj_size = total_len;
- ret = put_obj_meta(ctx, dest_obj, end + 1, NULL, attrset, category, PUT_OBJ_CREATE, NULL, &first_chunk, &manifest, &tag);
+ ret = put_obj_meta(ctx, dest_obj, end + 1, NULL, attrset, category, PUT_OBJ_CREATE, NULL, &first_chunk, &manifest, &tag, NULL);
if (mtime)
obj_stat(ctx, dest_obj, NULL, mtime, NULL, NULL, NULL);
}
manifest.obj_size = ofs;
- ret = put_obj_meta(ctx, dest_obj, end + 1, NULL, attrs, category, PUT_OBJ_CREATE, NULL, &first_chunk, &manifest, NULL);
+ ret = put_obj_meta(ctx, dest_obj, end + 1, NULL, attrs, category, PUT_OBJ_CREATE, NULL, &first_chunk, &manifest, NULL, NULL);
if (mtime)
obj_stat(ctx, dest_obj, NULL, mtime, NULL, NULL, NULL);
}
int RGWRados::complete_update_index(rgw_bucket& bucket, string& oid, string& tag, uint64_t epoch, uint64_t size,
- utime_t& ut, string& etag, string& content_type, bufferlist *acl_bl, RGWObjCategory category)
+ utime_t& ut, string& etag, string& content_type, bufferlist *acl_bl, RGWObjCategory category,
+ list<string> *remove_objs)
{
if (bucket_is_system(bucket))
return 0;
ent.owner_display_name = owner.get_display_name();
ent.content_type = content_type;
- int ret = cls_obj_complete_add(bucket, tag, epoch, ent, category);
+ int ret = cls_obj_complete_add(bucket, tag, epoch, ent, category, remove_objs);
return ret;
}
if (update_index) {
if (ret >= 0) {
ret = complete_update_index(bucket, dst_obj.object, tag, epoch, size,
- ut, etag, content_type, &acl_bl, category);
+ ut, etag, content_type, &acl_bl, category, NULL);
} else {
int r = complete_update_index_cancel(bucket, dst_obj.object, tag);
if (r < 0) {
return r;
}
-int RGWRados::cls_obj_complete_op(rgw_bucket& bucket, uint8_t op, string& tag, uint64_t epoch, RGWObjEnt& ent, RGWObjCategory category)
+int RGWRados::cls_obj_complete_op(rgw_bucket& bucket, uint8_t op, string& tag, uint64_t epoch, RGWObjEnt& ent, RGWObjCategory category,
+ list<string> *remove_objs)
{
librados::IoCtx io_ctx;
string oid;
dir_meta.owner_display_name = ent.owner_display_name;
dir_meta.content_type = ent.content_type;
dir_meta.category = category;
- cls_rgw_bucket_complete_op(o, op, tag, epoch, ent.name, dir_meta);
+ cls_rgw_bucket_complete_op(o, op, tag, epoch, ent.name, dir_meta, remove_objs);
AioCompletion *c = librados::Rados::aio_create_completion(NULL, NULL, NULL);
r = io_ctx.aio_operate(oid, c, &o);
return r;
}
-int RGWRados::cls_obj_complete_add(rgw_bucket& bucket, string& tag, uint64_t epoch, RGWObjEnt& ent, RGWObjCategory category)
+int RGWRados::cls_obj_complete_add(rgw_bucket& bucket, string& tag, uint64_t epoch, RGWObjEnt& ent, RGWObjCategory category, list<string> *remove_objs)
{
- return cls_obj_complete_op(bucket, CLS_RGW_OP_ADD, tag, epoch, ent, category);
+ return cls_obj_complete_op(bucket, CLS_RGW_OP_ADD, tag, epoch, ent, category, remove_objs);
}
int RGWRados::cls_obj_complete_del(rgw_bucket& bucket, string& tag, uint64_t epoch, string& name)
{
RGWObjEnt ent;
ent.name = name;
- return cls_obj_complete_op(bucket, CLS_RGW_OP_DEL, tag, epoch, ent, RGW_OBJ_CATEGORY_NONE);
+ return cls_obj_complete_op(bucket, CLS_RGW_OP_DEL, tag, epoch, ent, RGW_OBJ_CATEGORY_NONE, NULL);
}
int RGWRados::cls_obj_complete_cancel(rgw_bucket& bucket, string& tag, string& name)
{
RGWObjEnt ent;
ent.name = name;
- return cls_obj_complete_op(bucket, CLS_RGW_OP_ADD, tag, 0, ent, RGW_OBJ_CATEGORY_NONE);
+ return cls_obj_complete_op(bucket, CLS_RGW_OP_ADD, tag, 0, ent, RGW_OBJ_CATEGORY_NONE, NULL);
}
int RGWRados::cls_bucket_list(rgw_bucket& bucket, string start, string prefix,
virtual int put_obj_meta(void *ctx, rgw_obj& obj, uint64_t size, time_t *mtime,
map<std::string, bufferlist>& attrs, RGWObjCategory category, int flags,
map<std::string, bufferlist>* rmattrs, const bufferlist *data,
- RGWObjManifest *manifest, const string *ptag);
+ RGWObjManifest *manifest, const string *ptag, list<string> *remove_objs);
virtual int put_obj_data(void *ctx, rgw_obj& obj, const char *data,
off_t ofs, size_t len, bool exclusive);
virtual int aio_put_obj_data(void *ctx, rgw_obj& obj, bufferlist& bl,
int flags = PUT_OBJ_CREATE;
if (exclusive)
flags |= PUT_OBJ_EXCL;
- int ret = put_obj_meta(ctx, obj, len, mtime, attrs, RGW_OBJ_CATEGORY_NONE, flags, NULL, &bl, NULL, NULL);
+ int ret = put_obj_meta(ctx, obj, len, mtime, attrs, RGW_OBJ_CATEGORY_NONE, flags, NULL, &bl, NULL, NULL, NULL);
return ret;
}
virtual int aio_wait(void *handle);
int cls_obj_prepare_op(rgw_bucket& bucket, uint8_t op, string& tag,
string& name, string& locator);
int cls_obj_complete_op(rgw_bucket& bucket, uint8_t op, string& tag, uint64_t epoch,
- RGWObjEnt& ent, RGWObjCategory category);
- int cls_obj_complete_add(rgw_bucket& bucket, string& tag, uint64_t epoch, RGWObjEnt& ent, RGWObjCategory category);
+ RGWObjEnt& ent, RGWObjCategory category, list<string> *remove_objs);
+ int cls_obj_complete_add(rgw_bucket& bucket, string& tag, uint64_t epoch, RGWObjEnt& ent, RGWObjCategory category, list<string> *remove_objs);
int cls_obj_complete_del(rgw_bucket& bucket, string& tag, uint64_t epoch, string& name);
int cls_obj_complete_cancel(rgw_bucket& bucket, string& tag, string& name);
int cls_bucket_list(rgw_bucket& bucket, string start, string prefix, uint32_t num,
int prepare_update_index(RGWObjState *state, rgw_bucket& bucket,
rgw_obj& oid, string& tag);
int complete_update_index(rgw_bucket& bucket, string& oid, string& tag, uint64_t epoch, uint64_t size,
- utime_t& ut, string& etag, string& content_type, bufferlist *acl_bl, RGWObjCategory category);
+ utime_t& ut, string& etag, string& content_type, bufferlist *acl_bl, RGWObjCategory category,
+ list<string> *remove_objs);
int complete_update_index_del(rgw_bucket& bucket, string& oid, string& tag, uint64_t epoch) {
return cls_obj_complete_del(bucket, tag, epoch, oid);
}