cls_user_bucket_entry old_entry;
ret = get_existing_bucket_entry(hctx, key, old_entry);
- if (ret == -ENOENT)
+ if (ret == -ENOENT) {
+ if (!op.add)
continue; /* racing bucket removal */
+ ret = 0;
+ }
+
if (ret < 0) {
CLS_LOG(0, "ERROR: get_existing_bucket_entry() key=%s returned %d", key.c_str(), ret);
return ret;
using namespace librados;
-void cls_user_set_buckets(librados::ObjectWriteOperation& op, list<cls_user_bucket_entry>& entries)
+void cls_user_set_buckets(librados::ObjectWriteOperation& op, list<cls_user_bucket_entry>& entries, bool add)
{
bufferlist in;
cls_user_set_buckets_op call;
call.entries = entries;
+ call.add = add;
call.time = ceph_clock_now(NULL);
::encode(call, in);
op.exec("user", "set_buckets_info", in);
* user objclass
*/
-void cls_user_set_buckets(librados::ObjectWriteOperation& op, list<cls_user_bucket_entry>& entries);
+void cls_user_set_buckets(librados::ObjectWriteOperation& op, list<cls_user_bucket_entry>& entries, bool add);
void cls_user_complete_stats_sync(librados::ObjectWriteOperation& op);
void cls_user_remove_bucket(librados::ObjectWriteOperation& op, const cls_user_bucket& bucket);
void cls_user_bucket_list(librados::ObjectReadOperation& op,
struct cls_user_set_buckets_op {
list<cls_user_bucket_entry> entries;
+ bool add;
utime_t time; /* op time */
- cls_user_set_buckets_op() {}
+ cls_user_set_buckets_op() : add(false) {}
void encode(bufferlist& bl) const {
ENCODE_START(1, 1, bl);
::encode(entries, bl);
+ ::encode(add, bl);
::encode(time, bl);
ENCODE_FINISH(bl);
}
void decode(bufferlist::iterator& bl) {
DECODE_START(1, bl);
::decode(entries, bl);
+ ::decode(add, bl);
::decode(time, bl);
DECODE_FINISH(bl);
}
cerr << "failed to read user buckets: " << cpp_strerror(-ret) << std::endl;
return -ret;
}
-
map<string, RGWBucketEnt>& buckets = user_buckets.get_buckets();
for (map<string, RGWBucketEnt>::iterator i = buckets.begin();
i != buckets.end();
list<cls_user_bucket_entry> entries;
entries.push_back(entry);
- r = cls_user_update_buckets(user_obj, entries);
+ r = cls_user_update_buckets(user_obj, entries, false);
if (r < 0) {
ldout(cct, 20) << "cls_user_update_buckets() returned " << r << dendl;
return r;
rgw_get_buckets_obj(user_id, buckets_obj_id);
rgw_obj obj(zone.user_uid_pool, buckets_obj_id);
- int r = cls_user_update_buckets(obj, entries);
+ int r = cls_user_update_buckets(obj, entries, false);
if (r < 0) {
ldout(cct, 20) << "cls_user_update_buckets() returned " << r << dendl;
return r;
return 0;
}
-int RGWRados::cls_user_update_buckets(rgw_obj& obj, list<cls_user_bucket_entry>& entries)
+int RGWRados::cls_user_update_buckets(rgw_obj& obj, list<cls_user_bucket_entry>& entries, bool add)
{
bufferlist bl;
librados::IoCtx io_ctx;
return r;
librados::ObjectWriteOperation op;
- cls_user_set_buckets(op, entries);
+ cls_user_set_buckets(op, entries, add);
r = io_ctx.operate(oid, &op);
if (r < 0)
return r;
list<cls_user_bucket_entry> l;
l.push_back(entry);
- return cls_user_update_buckets(obj, l);
+ return cls_user_update_buckets(obj, l, true);
}
int RGWRados::cls_user_remove_bucket(rgw_obj& obj, const cls_user_bucket& bucket)
list<cls_user_bucket_entry>& entries,
string *out_marker, bool *truncated);
int cls_user_add_bucket(rgw_obj& obj, const cls_user_bucket_entry& entry);
- int cls_user_update_buckets(rgw_obj& obj, list<cls_user_bucket_entry>& entries);
+ int cls_user_update_buckets(rgw_obj& obj, list<cls_user_bucket_entry>& entries, bool add);
int cls_user_complete_stats_sync(rgw_obj& obj);
int complete_sync_user_stats(const string& user_id);
int cls_user_add_bucket(rgw_obj& obj, list<cls_user_bucket_entry>& entries);