map<std::string, bufferlist>& attrs, RGWObjCategory category, bool exclusive,
map<std::string, bufferlist>* rmattrs) = 0;
virtual int put_obj_data(void *ctx, rgw_obj& obj, const char *data,
- off_t ofs, size_t len) = 0;
+ off_t ofs, size_t len, bool exclusive) = 0;
virtual int aio_put_obj_data(void *ctx, rgw_obj& obj, const char *data,
- off_t ofs, size_t len, void **handle) { return -ENOTSUP; }
+ off_t ofs, size_t len, bool exclusive, void **handle) { return -ENOTSUP; }
/* note that put_obj doesn't set category on an object, only use it for none user objects */
- int put_obj(void *ctx, rgw_obj& obj, const char *data, size_t len,
+ int put_obj(void *ctx, rgw_obj& obj, const char *data, size_t len, bool exclusive,
time_t *mtime, map<std::string, bufferlist>& attrs) {
- int ret = put_obj_data(ctx, obj, data, -1, len);
- if (ret >= 0) {
+ int ret = put_obj_data(ctx, obj, data, -1, len, exclusive);
+ if (ret >= 0 && (attrs.size() || mtime)) {
ret = put_obj_meta(ctx, obj, len, mtime, attrs, RGW_OBJ_CATEGORY_NONE, false, NULL);
}
return ret;
/* The bucket here can either be the bucket name identifier, or the ID
* in period format: ".123" */
virtual int get_bucket_info(void *ctx, string& bucket, RGWBucketInfo& info) = 0;
- virtual int put_bucket_info(string& bucket_name, RGWBucketInfo& info) = 0;
+ virtual int put_bucket_info(string& bucket_name, RGWBucketInfo& info, bool exclusive) = 0;
virtual int remove_temp_objects(string date, string time) {
info.subusers[subuser] = u;
}
- if ((err = rgw_store_user_info(info)) < 0) {
+ if ((err = rgw_store_user_info(info, false)) < 0) {
cerr << "error storing user info: " << cpp_strerror(-err) << std::endl;
break;
}
keys_map->erase(kiter);
}
}
- if ((err = rgw_store_user_info(info)) < 0) {
+ if ((err = rgw_store_user_info(info, false)) < 0) {
cerr << "error storing user info: " << cpp_strerror(-err) << std::endl;
break;
}
} else {
rgw_remove_key_index(kiter->second);
keys_map->erase(kiter);
- if ((err = rgw_store_user_info(info)) < 0) {
+ if ((err = rgw_store_user_info(info, false)) < 0) {
cerr << "error storing user info: " << cpp_strerror(-err) << std::endl;
break;
}
int ret;
info.suspended = disable;
- ret = rgw_store_user_info(info);
+ ret = rgw_store_user_info(info, false);
if (ret < 0) {
cerr << "ERROR: failed to store user info user=" << user_id << " ret=" << ret << std::endl;
return 1;
}
int RGWFS::put_obj_data(void *ctx, rgw_obj& obj, const char *data,
- off_t ofs, size_t size)
+ off_t ofs, size_t size, bool exclusive)
{
rgw_bucket& bucket = obj.bucket;
std::string& oid = obj.object;
}
attrs = attrset;
- ret = put_obj(ctx, dest_obj, data, ret, mtime, attrs);
+ ret = put_obj(ctx, dest_obj, data, ret, false, mtime, attrs);
return ret;
}
return -ENOTSUP;
}
-int RGWFS::put_bucket_info(string& bucket_name, RGWBucketInfo& info)
+int RGWFS::put_bucket_info(string& bucket_name, RGWBucketInfo& info, bool exclusive)
{
return -ENOTSUP;
}
map<std::string, bufferlist>& attrs, RGWObjCategory category, bool exclusive,
map<std::string, bufferlist> *rmattrs);
int put_obj_data(void *ctx, rgw_obj& obj, const char *data,
- off_t ofs, size_t size);
+ off_t ofs, size_t size, bool exclusive);
int copy_obj(void *ctx, rgw_obj& dest_obj,
rgw_obj& src_obj,
time_t *mtime,
int obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime, map<string, bufferlist> *attrs);
virtual int get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& info);
- virtual int put_bucket_info(string& bucket_name, RGWBucketInfo& info);
+ virtual int put_bucket_info(string& bucket_name, RGWBucketInfo& info, bool exclusive);
};
#endif
void *handle;
ret = rgwstore->aio_put_obj_data(s->obj_ctx, obj,
data,
- ((ofs == 0) ? -1 : ofs), len, &handle);
+ ((ofs == 0) ? -1 : ofs), len, false, &handle);
if (ret < 0)
goto done_err;
RGWBucketInfo info;
info.bucket = bucket;
info.owner = owner;
- ret = store_bucket_info(info);
+ ret = store_bucket_info(info, exclusive);
if (ret < 0) {
dout(0) << "failed to store bucket info, removing bucket" << dendl;
delete_bucket(bucket);
return ret;
}
-int RGWRados::store_bucket_info(RGWBucketInfo& info)
+int RGWRados::store_bucket_info(RGWBucketInfo& info, bool exclusive)
{
bufferlist bl;
::encode(info, bl);
- int ret = rgw_put_obj(info.owner, pi_buckets_rados, info.bucket.name, bl.c_str(), bl.length());
+ int ret = rgw_put_obj(info.owner, pi_buckets_rados, info.bucket.name, bl.c_str(), bl.length(), exclusive);
if (ret < 0)
return ret;
char bucket_char[16];
snprintf(bucket_char, sizeof(bucket_char), ".%lld", (long long unsigned)info.bucket.bucket_id);
string bucket_id_string(bucket_char);
- ret = rgw_put_obj(info.owner, pi_buckets_rados, bucket_id_string, bl.c_str(), bl.length());
+ ret = rgw_put_obj(info.owner, pi_buckets_rados, bucket_id_string, bl.c_str(), bl.length(), false);
+ if (ret < 0) {
+ dout(0) << "ERROR: failed to store " << pi_buckets_rados << ":" << bucket_id_string << " ret=" << ret << dendl;
+ return ret;
+ }
dout(0) << "store_bucket_info: bucket=" << info.bucket << " owner " << info.owner << dendl;
return 0;
* Returns: 0 on success, -ERR# otherwise.
*/
int RGWRados::put_obj_data(void *ctx, rgw_obj& obj,
- const char *data, off_t ofs, size_t len)
+ const char *data, off_t ofs, size_t len, bool exclusive)
{
void *handle;
- int r = aio_put_obj_data(ctx, obj, data, ofs, len, &handle);
+ int r = aio_put_obj_data(ctx, obj, data, ofs, len, exclusive, &handle);
if (r < 0)
return r;
return aio_wait(handle);
}
int RGWRados::aio_put_obj_data(void *ctx, rgw_obj& obj,
- const char *data, off_t ofs, size_t len,
+ const char *data, off_t ofs, size_t len, bool exclusive,
void **handle)
{
rgw_bucket bucket;
AioCompletion *c = librados::Rados::aio_create_completion(NULL, NULL, NULL);
*handle = c;
+ ObjectWriteOperation op;
- if (ofs == -1) {
- // write_full wants to write the complete bufferlist, not part of it
- assert(bl.length() == len);
+ if (exclusive)
+ op.create(true);
- r = io_ctx.aio_write_full(oid, c, bl);
- }
- else {
- r = io_ctx.aio_write(oid, c, bl, len, ofs);
+ if (ofs == -1) {
+ op.write_full(bl);
+ } else {
+ op.write(ofs, bl);
}
+ r = io_ctx.aio_operate(oid, c, &op);
if (r < 0)
return r;
// In the first call to put_obj_data, we pass ofs == -1 so that it will do
// a write_full, wiping out whatever was in the object before this
- r = put_obj_data(ctx, tmp_obj, data, ((ofs == 0) ? -1 : ofs), ret);
+ r = put_obj_data(ctx, tmp_obj, data, ((ofs == 0) ? -1 : ofs), ret, false);
free(data);
if (r < 0)
goto done_err;
info.flags |= BUCKET_SUSPENDED;
}
- r = put_bucket_info(bucket.name, info);
+ r = put_bucket_info(bucket.name, info, false);
if (r < 0) {
dout(0) << "put_bucket_info on bucket=" << bucket.name << " returned err=" << r << ", skipping bucket" << dendl;
ret = r;
return 0;
}
-int RGWRados::put_bucket_info(string& bucket_name, RGWBucketInfo& info)
+int RGWRados::put_bucket_info(string& bucket_name, RGWBucketInfo& info, bool exclusive)
{
bufferlist bl;
string unused;
- int ret = rgw_put_obj(unused, pi_buckets_rados, bucket_name, bl.c_str(), bl.length());
+ int ret = rgw_put_obj(unused, pi_buckets_rados, bucket_name, bl.c_str(), bl.length(), exclusive);
return ret;
}
int delete_obj_impl(void *ctx, rgw_obj& src_obj, bool sync);
int select_bucket_placement(std::string& bucket_name, rgw_bucket& bucket);
- int store_bucket_info(RGWBucketInfo& info);
+ int store_bucket_info(RGWBucketInfo& info, bool exclusive);
public:
RGWRados() : lock("rados_timer_lock"), timer(NULL), watcher(NULL), watch_handle(0) {}
map<std::string, bufferlist>& attrs, RGWObjCategory category, bool exclusive,
map<std::string, bufferlist>* rmattrs);
virtual int put_obj_data(void *ctx, rgw_obj& obj, const char *data,
- off_t ofs, size_t len);
+ off_t ofs, size_t len, bool exclusive);
virtual int aio_put_obj_data(void *ctx, rgw_obj& obj, const char *data,
- off_t ofs, size_t len, void **handle);
+ off_t ofs, size_t len, bool exclusive, void **handle);
virtual int aio_wait(void *handle);
virtual bool aio_completed(void *handle);
virtual int clone_objs(void *ctx, rgw_obj& dst_obj,
int decode_policy(bufferlist& bl, ACLOwner *owner);
int get_bucket_stats(rgw_bucket& bucket, map<RGWObjCategory, RGWBucketStats>& stats);
virtual int get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& info);
- virtual int put_bucket_info(string& bucket_name, RGWBucketInfo& info);
+ virtual int put_bucket_info(string& bucket_name, RGWBucketInfo& info, bool exclusive);
int cls_rgw_init_index(rgw_bucket& bucket, string& oid);
int cls_obj_prepare_op(rgw_bucket& bucket, uint8_t op, string& tag,
static map<string, string> ext_mime_map;
-int rgw_put_obj(string& uid, rgw_bucket& bucket, string& oid, const char *data, size_t size)
+int rgw_put_obj(string& uid, rgw_bucket& bucket, string& oid, const char *data, size_t size, bool exclusive)
{
map<string,bufferlist> attrs;
rgw_obj obj(bucket, oid);
- int ret = rgwstore->put_obj(NULL, obj, data, size, NULL, attrs);
+ int ret = rgwstore->put_obj(NULL, obj, data, size, exclusive, NULL, attrs);
if (ret == -ENOENT) {
ret = rgwstore->create_bucket(uid, bucket, attrs, true); //all callers are using system buckets
if (ret >= 0)
- ret = rgwstore->put_obj(NULL, obj, data, size, NULL, attrs);
+ ret = rgwstore->put_obj(NULL, obj, data, size, exclusive, NULL, attrs);
}
return ret;
#include "rgw_common.h"
-int rgw_put_obj(string& uid, rgw_bucket& bucket, string& oid, const char *data, size_t size);
+int rgw_put_obj(string& uid, rgw_bucket& bucket, string& oid, const char *data, size_t size, bool exclusive);
int rgw_get_obj(void *ctx, rgw_bucket& bucket, string& key, bufferlist& bl);
int rgw_tools_init(CephContext *cct);
* Save the given user information to storage.
* Returns: 0 on success, -ERR# on failure.
*/
-int rgw_store_user_info(RGWUserInfo& info)
+int rgw_store_user_info(RGWUserInfo& info, bool exclusive)
{
bufferlist bl;
info.encode(bl);
::encode(ui, uid_bl);
::encode(info, uid_bl);
- ret = rgw_put_obj(info.user_id, ui_uid_bucket, info.user_id, uid_bl.c_str(), uid_bl.length());
+ ret = rgw_put_obj(info.user_id, ui_uid_bucket, info.user_id, uid_bl.c_str(), uid_bl.length(), exclusive);
if (ret < 0)
return ret;
if (info.user_email.size()) {
- ret = rgw_put_obj(info.user_id, ui_email_bucket, info.user_email, uid_bl.c_str(), uid_bl.length());
+ ret = rgw_put_obj(info.user_id, ui_email_bucket, info.user_email, uid_bl.c_str(), uid_bl.length(), exclusive);
if (ret < 0)
return ret;
}
map<string, RGWAccessKey>::iterator iter = info.access_keys.begin();
for (; iter != info.access_keys.end(); ++iter) {
RGWAccessKey& k = iter->second;
- ret = rgw_put_obj(k.id, ui_key_bucket, k.id, uid_bl.c_str(), uid_bl.length());
+ ret = rgw_put_obj(k.id, ui_key_bucket, k.id, uid_bl.c_str(), uid_bl.length(), exclusive);
if (ret < 0)
return ret;
}
map<string, RGWAccessKey>::iterator siter;
for (siter = info.swift_keys.begin(); siter != info.swift_keys.end(); ++siter) {
RGWAccessKey& k = siter->second;
- ret = rgw_put_obj(info.user_id, ui_swift_bucket, k.id, uid_bl.c_str(), uid_bl.length());
+ ret = rgw_put_obj(info.user_id, ui_swift_bucket, k.id, uid_bl.c_str(), uid_bl.length(), exclusive);
if (ret < 0)
return ret;
}
* Save the given user information to storage.
* Returns: 0 on success, -ERR# on failure.
*/
-extern int rgw_store_user_info(RGWUserInfo& info);
+extern int rgw_store_user_info(RGWUserInfo& info, bool exclusive);
/**
* Given an email, finds the user info associated with it.
* returns: 0 on success, -ERR# on failure (including nonexistence)