}
#endif
-int rgw_bucket_set_attrs(RGWRados *store, rgw_obj& obj,
+int rgw_bucket_set_attrs(RGWRados *store, rgw_bucket& bucket,
map<string, bufferlist>& attrs,
map<string, bufferlist>* rmattrs,
RGWObjVersionTracker *objv_tracker)
{
- return store->meta_mgr->set_attrs(bucket_meta_handler, obj.bucket.name,
+ string oid;
+ store->get_bucket_meta_oid(bucket, oid);
+ rgw_obj obj(store->zone.domain_root, oid);
+ return store->meta_mgr->set_attrs(bucket_meta_handler, oid,
obj, attrs, rmattrs, objv_tracker);
}
bci.info.bucket.index_pool = old_bci.info.bucket.index_pool;
}
- ret = store->put_bucket_info(entry, bci.info, false, &objv_tracker, mtime, &bci.attrs);
+#warning need to take care of different routes here
+ ret = store->put_bucket_info(entry, bci.info, false, &objv_tracker, mtime, &bci.attrs, false);
if (ret < 0)
return ret;
extern int rgw_remove_object(RGWRados *store, rgw_bucket& bucket, std::string& object);
extern int rgw_remove_bucket(RGWRados *store, rgw_bucket& bucket, bool delete_children);
-extern int rgw_bucket_set_attrs(RGWRados *store, rgw_obj& obj,
+extern int rgw_bucket_set_attrs(RGWRados *store, rgw_bucket& obj,
map<string, bufferlist>& attrs,
map<string, bufferlist>* rmattrs,
RGWObjVersionTracker *objv_tracker);
string region;
time_t creation_time;
string placement_rule;
+ bool has_instance_obj;
void encode(bufferlist& bl) const {
- ENCODE_START(7, 4, bl);
+ ENCODE_START(8, 4, bl);
::encode(bucket, bl);
::encode(owner, bl);
::encode(flags, bl);
::encode(region, bl);
::encode(creation_time, bl);
::encode(placement_rule, bl);
+ ::encode(has_instance_obj, bl);
ENCODE_FINISH(bl);
}
void decode(bufferlist::iterator& bl) {
::decode(creation_time, bl);
if (struct_v >= 7)
::decode(placement_rule, bl);
+ if (struct_v >= 8)
+ ::decode(has_instance_obj, bl);
DECODE_FINISH(bl);
}
void dump(Formatter *f) const;
void decode_json(JSONObj *obj);
- RGWBucketInfo() : flags(0), creation_time(0) {}
+ RGWBucketInfo() : flags(0), creation_time(0), has_instance_obj(false) {}
};
WRITE_CLASS_ENCODER(RGWBucketInfo)
+struct RGWBucketEntryPoint
+{
+ rgw_bucket bucket;
+
+ bool has_bucket_info;
+ RGWBucketInfo old_bucket_info;
+
+ void encode(bufferlist& bl) const {
+ ENCODE_START(8, 8, bl);
+ ::encode(bucket, bl);
+ ENCODE_FINISH(bl);
+ }
+ void decode(bufferlist::iterator& bl) {
+ bufferlist::iterator orig_iter = bl;
+ DECODE_START_LEGACY_COMPAT_LEN_32(8, 4, 4, bl);
+ if (struct_v < 8) {
+ /* ouch, old entry, contains the bucket info itself */
+ old_bucket_info.decode(orig_iter);
+ has_bucket_info = true;
+ return;
+ }
+ has_bucket_info = false;
+ ::decode(bucket, bl);
+ DECODE_FINISH(bl);
+ }
+};
+WRITE_CLASS_ENCODER(RGWBucketEntryPoint)
+
struct RGWBucketStats
{
RGWObjCategory category;
encode_json("flags", flags, f);
encode_json("region", region, f);
encode_json("placement_rule", region, f);
+ encode_json("has_instance_obj", has_instance_obj, f);
}
void RGWBucketInfo::decode_json(JSONObj *obj) {
JSONDecoder::decode_json("flags", flags, obj);
JSONDecoder::decode_json("region", region, obj);
JSONDecoder::decode_json("placement_rule", region, obj);
+ JSONDecoder::decode_json("has_instance_obj", has_instance_obj, obj);
}
void RGWObjEnt::dump(Formatter *f) const
if (s->object) {
ret = store->set_attrs(s->obj_ctx, obj, attrs, &rmattrs, ptracker);
} else {
- ret = rgw_bucket_set_attrs(store, obj, attrs, &rmattrs, ptracker);
+ ret = rgw_bucket_set_attrs(store, obj.bucket, attrs, &rmattrs, ptracker);
}
}
if (s->object) {
ret = store->set_attrs(s->obj_ctx, obj, attrs, NULL, ptracker);
} else {
- ret = rgw_bucket_set_attrs(store, obj, attrs, NULL, ptracker);
+ ret = rgw_bucket_set_attrs(store, obj.bucket, attrs, NULL, ptracker);
}
}
time(&info.creation_time);
else
info.creation_time = creation_time;
- ret = put_bucket_info(bucket.name, info, exclusive, &objv_tracker, 0, &attrs);
+ ret = put_bucket_info(bucket.name, info, exclusive, &objv_tracker, 0, &attrs, true);
if (ret == -EEXIST) {
librados::IoCtx index_ctx; // context for new bucket
int r = open_bucket_index_ctx(bucket, index_ctx);
return r;
index_ctx.remove(dir_oid);
- /* we need this for this objv_tracker */
+ /* we need to updated objv_tracker, but we don't want the old cruft there */
+ objv_tracker = RGWObjVersionTracker();
r = get_bucket_info(NULL, bucket.name, info, &objv_tracker, NULL);
if (r < 0) {
if (r == -ENOENT) {
info.owner = owner.get_id();
- r = put_bucket_info(bucket.name, info, false, &objv_tracker, 0, &attrs);
+ r = put_bucket_info(bucket.name, info, false, &objv_tracker, 0, &attrs, false);
if (r < 0) {
ldout(cct, 0) << "NOTICE: put_bucket_info on bucket=" << bucket.name << " returned err=" << r << dendl;
return r;
info.flags |= BUCKET_SUSPENDED;
}
- r = put_bucket_info(bucket.name, info, false, &objv_tracker, 0, &attrs);
+ r = put_bucket_info(bucket.name, info, false, &objv_tracker, 0, &attrs, false);
if (r < 0) {
ldout(cct, 0) << "NOTICE: put_bucket_info on bucket=" << bucket.name << " returned err=" << r << ", skipping bucket" << dendl;
ret = r;
return 0;
}
+void RGWRados::get_bucket_meta_oid(rgw_bucket& bucket, string& oid)
+{
+ oid = ".bucket.meta." + bucket.bucket_id;
+}
+
int RGWRados::get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& info, RGWObjVersionTracker *objv_tracker,
time_t *pmtime, map<string, bufferlist> *pattrs)
{
bufferlist bl;
- int ret = rgw_get_system_obj(this, ctx, zone.domain_root, bucket_name, bl, objv_tracker, pmtime, pattrs);
+ RGWObjVersionTracker ot;
+ int ret = rgw_get_system_obj(this, ctx, zone.domain_root, bucket_name, bl, &ot, pmtime, pattrs);
if (ret < 0) {
info.bucket.name = bucket_name; /* only init this field */
return ret;
}
+ RGWBucketEntryPoint entry_point;
bufferlist::iterator iter = bl.begin();
try {
- ::decode(info, iter);
+ ::decode(entry_point, iter);
} catch (buffer::error& err) {
ldout(cct, 0) << "ERROR: could not decode buffer info, caught buffer::error" << dendl;
return -EIO;
}
- ldout(cct, 20) << "rgw_get_bucket_info: bucket=" << info.bucket << " owner " << info.owner << dendl;
+ if (entry_point.has_bucket_info) {
+ info = entry_point.old_bucket_info;
+ ldout(cct, 20) << "rgw_get_bucket_info: old bucket info, bucket=" << info.bucket << " owner " << info.owner << dendl;
+ return 0;
+ }
+
+ ldout(cct, 20) << "rgw_get_bucket_info: bucket instance: " << entry_point.bucket << dendl;
+
+ if (pattrs)
+ pattrs->clear();
+
+ /* read bucket instance info */
+
+ string oid;
+ get_bucket_meta_oid(entry_point.bucket, oid);
+
+ ldout(cct, 20) << "reading from " << zone.domain_root << ":" << oid << dendl;
+
+ bufferlist epbl;
+
+ ret = rgw_get_system_obj(this, ctx, zone.domain_root, oid, epbl, objv_tracker, pmtime, pattrs);
+ if (ret < 0) {
+ info.bucket.name = bucket_name; /* only init this field */
+ return ret;
+ }
+ iter = epbl.begin();
+ try {
+ ::decode(info, iter);
+ } catch (buffer::error& err) {
+ ldout(cct, 0) << "ERROR: could not decode buffer info, caught buffer::error" << dendl;
+ return -EIO;
+ }
return 0;
}
int RGWRados::put_bucket_info(string& bucket_name, RGWBucketInfo& info, bool exclusive, RGWObjVersionTracker *objv_tracker,
- time_t mtime, map<string, bufferlist> *pattrs)
+ time_t mtime, map<string, bufferlist> *pattrs, bool create_entry_point)
{
bufferlist bl;
::encode(info, bl);
- int ret = rgw_bucket_store_info(this, info.bucket.name, bl, exclusive, pattrs, objv_tracker, mtime);
+ bool create_head = !info.has_instance_obj || create_entry_point;
+
+ info.has_instance_obj = true;
+
+ string oid;
+ get_bucket_meta_oid(info.bucket, oid);
+ int ret = rgw_bucket_store_info(this, oid, bl, exclusive, pattrs, objv_tracker, mtime);
+ if (ret < 0) {
+ return ret;
+ }
+
+ if (!create_head)
+ return 0; /* done! */
+
+ RGWBucketEntryPoint entry_point;
+ entry_point.bucket = info.bucket;
+ bufferlist epbl;
+ ::encode(entry_point, epbl);
+ RGWObjVersionTracker ot;
+ ret = rgw_bucket_store_info(this, info.bucket.name, epbl, exclusive, pattrs, &ot, mtime);
+
+ if (exclusive && ret == -EEXIST) {
+ rgw_obj obj(zone.domain_root, oid);
+ int r = delete_obj(NULL, obj);
+ if (r < 0) {
+ ldout(cct, 0) << "ERROR: failed removing object " << obj << " when trying to clean up" << dendl;
+ }
+ }
return ret;
}
int decode_policy(bufferlist& bl, ACLOwner *owner);
int get_bucket_stats(rgw_bucket& bucket, uint64_t *bucket_ver, uint64_t *master_ver, map<RGWObjCategory, RGWBucketStats>& stats);
+ void get_bucket_meta_oid(rgw_bucket& bucket, string& oid);
virtual int get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& info, RGWObjVersionTracker *objv_tracker,
time_t *pmtime, map<string, bufferlist> *pattrs = NULL);
virtual int put_bucket_info(string& bucket_name, RGWBucketInfo& info, bool exclusive, RGWObjVersionTracker *objv_tracker,
- time_t mtime, map<string, bufferlist> *pattrs);
+ time_t mtime, map<string, bufferlist> *pattrs, bool create_entry_point);
int cls_rgw_init_index(librados::IoCtx& io_ctx, librados::ObjectWriteOperation& op, string& oid);
int cls_obj_prepare_op(rgw_bucket& bucket, RGWModifyOp op, string& tag,