void zero(uint64_t off, uint64_t len);
void rmxattr(const char *name);
void setxattr(const char *name, const bufferlist& bl);
- void cmpxattr(const char *name, const bufferlist& val, int op, int mode);
+ void cmpxattr(const char *name, const bufferlist& bl);
void tmap_update(const bufferlist& cmdbl);
void clone_range(uint64_t dst_off,
const std::string& src_oid, uint64_t src_off,
o->setxattr(name, v);
}
-void librados::ObjectOperation::cmpxattr(const char *name, const bufferlist& v, int op, int mode)
+void librados::ObjectOperation::cmpxattr(const char *name, const bufferlist& v)
{
::ObjectOperation *o = (::ObjectOperation *)impl;
- o->cmpxattr(name, v, op, mode);
+ o->cmpxattr(name, v);
}
void librados::ObjectOperation::tmap_update(const bufferlist& cmdbl)
bl.append(s);
add_xattr(CEPH_OSD_OP_SETXATTR, name, bl);
}
+ void cmpxattr(const char *name, const bufferlist& bl) {
+ add_xattr(CEPH_OSD_OP_CMPXATTR, name, bl);
+ }
void rmxattr(const char *name) {
bufferlist bl;
add_xattr(CEPH_OSD_OP_RMXATTR, name, bl);
virtual int create_bucket(std::string& id, std::string& bucket, map<std::string, bufferlist>& attrs, bool exclusive = true, uint64_t auid = 0) = 0;
/** write an object to the storage device in the appropriate pool
with the given stats */
- virtual int put_obj_meta(std::string& id, rgw_obj& obj, time_t *mtime,
+ virtual int put_obj_meta(void *ctx, std::string& id, rgw_obj& obj, time_t *mtime,
map<std::string, bufferlist>& attrs, bool exclusive) = 0;
- virtual int put_obj_data(std::string& id, rgw_obj& obj, const char *data,
+ virtual int put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data,
off_t ofs, size_t len) = 0;
- virtual int aio_put_obj_data(std::string& id, rgw_obj& obj, const char *data,
+ virtual int aio_put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data,
off_t ofs, size_t len, void **handle) { return -ENOTSUP; }
- int put_obj(std::string& id, rgw_obj& obj, const char *data, size_t len,
+ int put_obj(void *ctx, std::string& id, rgw_obj& obj, const char *data, size_t len,
time_t *mtime, map<std::string, bufferlist>& attrs) {
- int ret = put_obj_data(id, obj, data, -1, len);
+ int ret = put_obj_data(ctx, id, obj, data, -1, len);
if (ret >= 0) {
- ret = put_obj_meta(id, obj, mtime, attrs, false);
+ ret = put_obj_meta(ctx, id, obj, mtime, attrs, false);
}
return ret;
}
* err: stores any errors resulting from the get of the original object
* Returns: 0 on success, -ERR# otherwise.
*/
- virtual int copy_obj(std::string& id, rgw_obj& dest_obj,
+ virtual int copy_obj(void *ctx, std::string& id, rgw_obj& dest_obj,
rgw_obj& src_obj,
time_t *mtime,
const time_t *mod_ptr,
* obj: name of the object to delete
* Returns: 0 on success, -ERR# otherwise.
*/
- virtual int delete_obj(std::string& id, rgw_obj& obj, bool sync = true) = 0;
+ virtual int delete_obj(void *ctx, std::string& id, rgw_obj& obj, bool sync = true) = 0;
/**
* Get data about an object out of RADOS and into memory.
* (if get_data==true) length of read data,
* (if get_data==false) length of the object
*/
- virtual int prepare_get_obj(rgw_obj& obj,
+ virtual int prepare_get_obj(void *ctx,
+ rgw_obj& obj,
off_t ofs, off_t *end,
map<string, bufferlist> *attrs,
const time_t *mod_ptr,
void **handle,
struct rgw_err *err) = 0;
- virtual int get_obj(void **handle, rgw_obj& obj,
+ virtual int get_obj(void *ctx, void **handle, rgw_obj& obj,
char **data, off_t ofs, off_t end) = 0;
virtual void finish_get_obj(void **handle) = 0;
- virtual int clone_range(rgw_obj& dst_obj, off_t dst_ofs,
+ virtual int clone_range(void *ctx, rgw_obj& dst_obj, off_t dst_ofs,
rgw_obj& src_obj, off_t src_ofs,
uint64_t size) = 0;
- virtual int clone_obj(rgw_obj& dst_obj, off_t dst_ofs,
+ virtual int clone_obj(void *ctx, rgw_obj& dst_obj, off_t dst_ofs,
rgw_obj& src_obj, off_t src_ofs,
uint64_t size, map<string, bufferlist> attrs) {
RGWCloneRangeInfo info;
info.dst_ofs = dst_ofs;
info.len = size;
v.push_back(info);
- return clone_objs(dst_obj, v, attrs, true);
+ return clone_objs(ctx, dst_obj, v, attrs, true);
}
- virtual int clone_objs(rgw_obj& dst_obj,
+ virtual int clone_objs(void *ctx, rgw_obj& dst_obj,
vector<RGWCloneRangeInfo>& ranges,
map<string, bufferlist> attrs, bool truncate_dest) { return -ENOTSUP; }
/**
* a simple object read without keeping state
*/
- virtual int read(rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl) = 0;
+ virtual int read(void *ctx, rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl) = 0;
/**
* Get the attributes for an object.
* dest: bufferlist to store the result in
* Returns: 0 on success, -ERR# otherwise.
*/
- virtual int get_attr(rgw_obj& obj, const char *name, bufferlist& dest) = 0;
+ virtual int get_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& dest) = 0;
/**
* Set an attr on an object.
* bl: the contents of the attr
* Returns: 0 on success, -ERR# otherwise.
*/
- virtual int set_attr(rgw_obj& obj, const char *name, bufferlist& bl) = 0;
+ virtual int set_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& bl) = 0;
virtual int get_bucket_id(std::string& bucket) { return -ENOTSUP; }
/**
* stat an object
*/
- virtual int obj_stat(rgw_obj& obj, uint64_t *psize, time_t *pmtime) = 0;
+ virtual int obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime) = 0;
virtual bool supports_tmap() { return false; }
static RGWAccess *init_storage_provider(const char *type, CephContext *cct);
static void close_storage();
static RGWAccess *store;
+
+ virtual void *create_context() { return NULL; }
+ virtual void destroy_context(void *ctx) {}
};
class RGWStoreManager {
if (ret && ret != -EEXIST)
goto done;
- ret = rgwstore->set_attr(obj, RGW_ATTR_ACL, aclbl);
+ ret = rgwstore->set_attr(NULL, obj, RGW_ATTR_ACL, aclbl);
if (ret < 0) {
cerr << "couldn't set acl on bucket" << std::endl;
}
string bucket_str(bucket);
string object_str(object);
rgw_obj obj(bucket_str, object_str);
- int ret = store->get_attr(obj, RGW_ATTR_ACL, bl);
+ int ret = store->get_attr(NULL, obj, RGW_ATTR_ACL, bl);
RGWAccessControlPolicy policy;
if (ret >= 0) {
bufferlist aclbl;
rgw_obj obj(bucket_str, no_oid);
- int r = rgwstore->get_attr(obj, RGW_ATTR_ACL, aclbl);
+ int r = rgwstore->get_attr(NULL, obj, RGW_ATTR_ACL, aclbl);
if (r >= 0) {
RGWAccessControlPolicy policy;
ACLOwner owner;
uint64_t size;
rgw_obj obj(log_bucket, oid);
- int r = store->obj_stat(obj, &size, NULL);
+ int r = store->obj_stat(NULL, obj, &size, NULL);
if (r < 0) {
cerr << "error while doing stat on " << log_bucket << ":" << oid
<< " " << cpp_strerror(-r) << std::endl;
return -r;
}
bufferlist bl;
- r = store->read(obj, 0, size, bl);
+ r = store->read(NULL, obj, 0, size, bl);
if (r < 0) {
cerr << "error while reading from " << log_bucket << ":" << oid
<< " " << cpp_strerror(-r) << std::endl;
bufferlist bl;
rgw_obj obj(bucket_str, no_object);
- ret = rgwstore->get_attr(obj, RGW_ATTR_ACL, bl);
+ ret = rgwstore->get_attr(NULL, obj, RGW_ATTR_ACL, bl);
if (ret < 0) {
RGW_LOG(0) << "can't read bucket acls: " << ret << dendl;
return ret;
public:
RGWCache() {}
- int put_obj_data(std::string& id, rgw_obj& obj, const char *data,
+ int put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data,
off_t ofs, size_t len);
- int get_obj(void **handle, rgw_obj& obj, char **data, off_t ofs, off_t end);
+ int get_obj(void *ctx, void **handle, rgw_obj& obj, char **data, off_t ofs, off_t end);
- int obj_stat(std::string& bucket, std::string& obj, uint64_t *psize, time_t *pmtime);
+ int obj_stat(void *ctx, std::string& bucket, std::string& obj, uint64_t *psize, time_t *pmtime);
- int delete_obj(std::string& id, rgw_obj& obj, bool sync);
+ int delete_obj(void *ctx, std::string& id, rgw_obj& obj, bool sync);
};
template <class T>
-int RGWCache<T>::delete_obj(std::string& id, rgw_obj& obj, bool sync)
+int RGWCache<T>::delete_obj(void *ctx, std::string& id, rgw_obj& obj, bool sync)
{
string& bucket = obj.bucket;
if (bucket[0] != '.')
- return T::delete_obj(id, obj, sync);
+ return T::delete_obj(ctx, id, obj, sync);
string name = normal_name(obj);
cache.remove(name);
ObjectCacheInfo info;
distribute(obj, info, REMOVE_OBJ);
- return T::delete_obj(id, obj, sync);
+ return T::delete_obj(ctx, id, obj, sync);
}
template <class T>
-int RGWCache<T>::get_obj(void **handle, rgw_obj& obj, char **data, off_t ofs, off_t end)
+int RGWCache<T>::get_obj(void *ctx, void **handle, rgw_obj& obj, char **data, off_t ofs, off_t end)
{
string& bucket = obj.bucket;
if (bucket[0] != '.' || ofs != 0)
- return T::get_obj(handle, obj, data, ofs, end);
+ return T::get_obj(ctx, handle, obj, data, ofs, end);
string& oid = obj.object;
string name = normal_name(bucket, oid);
memcpy(*data, bl.c_str(), bl.length());
return bl.length();
}
- int r = T::get_obj(handle, obj, data, ofs, end);
+ int r = T::get_obj(ctx, handle, obj, data, ofs, end);
if (r < 0) {
if (r == -ENOENT) { // only update ENOENT, we'd rather retry other errors
info.status = r;
}
template <class T>
-int RGWCache<T>::put_obj_data(std::string& id, rgw_obj& obj, const char *data,
+int RGWCache<T>::put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data,
off_t ofs, size_t len)
{
string& bucket = obj.bucket;
info.status = 0;
info.flags = CACHE_FLAG_DATA;
}
- int ret = T::put_obj_data(id, obj, data, ofs, len);
+ int ret = T::put_obj_data(ctx, id, obj, data, ofs, len);
if (cacheable) {
if (ret >= 0) {
cache.put(name, info);
}
template <class T>
-int RGWCache<T>::obj_stat(std::string& bucket, std::string& obj, uint64_t *psize, time_t *pmtime)
+int RGWCache<T>::obj_stat(void *ctx, std::string& bucket, std::string& obj, uint64_t *psize, time_t *pmtime)
{
if (bucket[0] != '.')
- return T::obj_stat(bucket, obj, psize, pmtime);
+ return T::obj_stat(ctx, bucket, obj, psize, pmtime);
string name = normal_name(bucket, obj);
mtime = info.meta.mtime;
goto done;
}
- r = T::obj_stat(bucket, obj, &size, &mtime);
+ r = T::obj_stat(ctx, bucket, obj, &size, &mtime);
if (r < 0) {
if (r == -ENOENT) {
info.status = r;
}
req_state::~req_state() {
- delete acl;
delete formatter;
free(os_user);
free(os_groups);
#define RGW_ATTR_BUCKETS RGW_ATTR_PREFIX "buckets"
#define RGW_ATTR_META_PREFIX RGW_ATTR_PREFIX "x-amz-meta-"
#define RGW_ATTR_CONTENT_TYPE RGW_ATTR_PREFIX "content_type"
+#define RGW_ATTR_ID_TAG RGW_ATTR_PREFIX "idtag"
#define RGW_BUCKETS_OBJ_PREFIX ".buckets"
struct RGWEnv *env;
+ void *obj_ctx;
+
req_state(struct RGWEnv *e);
~req_state();
};
::decode(ns, bl);
::decode(object, bl);
}
+
+ bool operator<(const rgw_obj& o) const {
+ return (bucket.compare(o.bucket) < 0) ||
+ (object.compare(o.object) < 0) ||
+ (ns.compare(o.ns) < 0);
+ }
};
WRITE_CLASS_ENCODER(rgw_obj)
}
}
-int RGWFS::obj_stat(rgw_obj& obj, uint64_t *psize, time_t *pmtime)
+int RGWFS::obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime)
{
return -ENOTSUP;
}
return 0;
}
-int RGWFS::put_obj_meta(std::string& id, rgw_obj& obj,
+int RGWFS::put_obj_meta(void *ctx, std::string& id, rgw_obj& obj,
time_t *mtime, map<string, bufferlist>& attrs, bool exclusive)
{
std::string& bucket = obj.bucket;
return -errno;
}
-int RGWFS::put_obj_data(std::string& id, rgw_obj& obj, const char *data,
+int RGWFS::put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data,
off_t ofs, size_t size)
{
std::string& bucket = obj.bucket;
return r;
}
-int RGWFS::copy_obj(std::string& id, rgw_obj& dest_obj,
+int RGWFS::copy_obj(void *ctx, std::string& id, rgw_obj& dest_obj,
rgw_obj& src_obj,
time_t *mtime,
const time_t *mod_ptr,
time_t lastmod;
map<string, bufferlist> attrset;
- ret = prepare_get_obj(src_obj, 0, &end, &attrset, mod_ptr, unmod_ptr, &lastmod,
+ ret = prepare_get_obj(ctx, src_obj, 0, &end, &attrset, mod_ptr, unmod_ptr, &lastmod,
if_match, if_nomatch, &total_len, &obj_size, &handle, err);
if (ret < 0)
return ret;
do {
- ret = get_obj(&handle, src_obj, &data, ofs, end);
+ ret = get_obj(ctx, &handle, src_obj, &data, ofs, end);
if (ret < 0)
return ret;
ofs += ret;
}
attrs = attrset;
- ret = put_obj(id, dest_obj, data, ret, mtime, attrs);
+ ret = put_obj(ctx, id, dest_obj, data, ret, mtime, attrs);
return ret;
}
}
-int RGWFS::delete_obj(std::string& id, rgw_obj& obj, bool sync)
+int RGWFS::delete_obj(void *ctx, std::string& id, rgw_obj& obj, bool sync)
{
std::string& bucket = obj.bucket;
std::string& oid = obj.object;
return attr_len;
}
-int RGWFS::get_attr(rgw_obj& obj, const char *name, bufferlist& dest)
+int RGWFS::get_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& dest)
{
std::string& bucket = obj.bucket;
std::string& oid = obj.object;
return r;
}
-int RGWFS::set_attr(rgw_obj& obj,
+int RGWFS::set_attr(void *ctx, rgw_obj& obj,
const char *name, bufferlist& bl)
{
std::string& bucket = obj.bucket;
return ret;
}
-int RGWFS::prepare_get_obj(rgw_obj& obj,
+int RGWFS::prepare_get_obj(void *ctx,
+ rgw_obj& obj,
off_t ofs, off_t *end,
map<string, bufferlist> *attrs,
const time_t *mod_ptr,
return r;
}
-int RGWFS::get_obj(void **handle, rgw_obj& obj, char **data, off_t ofs, off_t end)
+int RGWFS::get_obj(void *ctx, void **handle, rgw_obj& obj, char **data, off_t ofs, off_t end)
{
uint64_t len;
bufferlist bl;
}
}
-int RGWFS::read(rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl)
+int RGWFS::read(void *ctx, rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl)
{
std::string& bucket = obj.bucket;
std::string& oid = obj.object;
bool get_content_type, string& ns, bool *is_truncated, RGWAccessListFilter *filter);
int create_bucket(std::string& id, std::string& bucket, map<std::string, bufferlist>& attrs, bool exclusive, uint64_t auid=0);
- int put_obj_meta(std::string& id, rgw_obj& obj, time_t *mtime,
+ int put_obj_meta(void *ctx, std::string& id, rgw_obj& obj, time_t *mtime,
map<std::string, bufferlist>& attrs, bool exclusive);
- int put_obj_data(std::string& id, rgw_obj& obj, const char *data,
+ int put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data,
off_t ofs, size_t size);
- int clone_range(rgw_obj& dst_obj, off_t dst_ofs,
+ int clone_range(void *ctx, rgw_obj& dst_obj, off_t dst_ofs,
rgw_obj& src_obj, off_t src_ofs, uint64_t size) { return -ENOTSUP; }
- int copy_obj(std::string& id, rgw_obj& dest_obj,
+ int copy_obj(void *ctx, std::string& id, rgw_obj& dest_obj,
rgw_obj& src_obj,
time_t *mtime,
const time_t *mod_ptr,
map<std::string, bufferlist>& attrs,
struct rgw_err *err);
int delete_bucket(std::string& id, std::string& bucket);
- int delete_obj(std::string& id, rgw_obj& obj, bool sync);
+ int delete_obj(void *ctx, std::string& id, rgw_obj& obj, bool sync);
int get_attr(const char *name, int fd, char **attr);
int get_attr(const char *name, const char *path, char **attr);
- int get_attr(rgw_obj& obj, const char *name, bufferlist& dest);
- int set_attr(rgw_obj& obj, const char *name, bufferlist& bl);
+ int get_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& dest);
+ int set_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& bl);
- int prepare_get_obj(rgw_obj& obj,
+ int prepare_get_obj(void *ctx,
+ rgw_obj& obj,
off_t ofs, off_t *end,
map<std::string, bufferlist> *attrs,
const time_t *mod_ptr,
void **handle,
struct rgw_err *err);
- int get_obj(void **handle, rgw_obj& obj, char **data, off_t ofs, off_t end);
+ int get_obj(void *ctx, void **handle, rgw_obj& obj, char **data, off_t ofs, off_t end);
void finish_get_obj(void **handle);
- int read(rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl);
- int obj_stat(rgw_obj& obj, uint64_t *psize, time_t *pmtime);
+ int read(void *ctx, rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl);
+ int obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime);
};
#endif
rgw_env.init(fcgx->envp);
struct req_state *s = new req_state(&rgw_env);
+ s->obj_ctx = rgwstore->create_context();
RGWOp *op = NULL;
int init_error = 0;
int http_ret = s->err.http_ret;
handler->put_op(op);
+ rgwstore->destroy_context(s->obj_ctx);
delete s;
FCGX_Finish_r(fcgx);
delete fcgx;
* object: name of the object to get the ACL for.
* Returns: 0 on success, -ERR# otherwise.
*/
-static int get_policy_from_attr(RGWAccessControlPolicy *policy, rgw_obj& obj)
+static int get_policy_from_attr(void *ctx, RGWAccessControlPolicy *policy, rgw_obj& obj)
{
bufferlist bl;
int ret = 0;
if (obj.bucket.size()) {
- ret = rgwstore->get_attr(obj, RGW_ATTR_ACL, bl);
+ ret = rgwstore->get_attr(ctx, obj, RGW_ATTR_ACL, bl);
if (ret >= 0) {
bufferlist::iterator iter = bl.begin();
}
obj.init(bucket, oid, object);
- int ret = get_policy_from_attr(policy, obj);
+ int ret = get_policy_from_attr(s->obj_ctx, policy, obj);
if (ret == -ENOENT && object.size()) {
/* object does not exist checking the bucket's ACL to make sure
that we send a proper error code */
RGWAccessControlPolicy bucket_policy;
string no_object;
rgw_obj no_obj(bucket, no_object);
- ret = get_policy_from_attr(&bucket_policy, no_obj);
+ ret = get_policy_from_attr(s->obj_ctx, &bucket_policy, no_obj);
if (ret < 0)
return ret;
init_common();
obj.init(s->bucket_str, s->object_str);
- ret = rgwstore->prepare_get_obj(obj, ofs, &end, &attrs, mod_ptr,
+ ret = rgwstore->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);
if (ret < 0)
goto done;
goto done;
while (ofs <= end) {
- ret = rgwstore->get_obj(&handle, obj, &data, ofs, end);
+ ret = rgwstore->get_obj(s->obj_ctx, &handle, obj, &data, ofs, end);
if (ret < 0) {
goto done;
}
rgw_obj obj(rgw_root_bucket, s->bucket_str);
- int r = get_policy_from_attr(&old_policy, obj);
+ int r = get_policy_from_attr(s->obj_ctx, &old_policy, obj);
if (r >= 0) {
if (old_policy.get_owner().get_id().compare(s->user.user_id) != 0) {
ret = -EEXIST;
// For the first call to put_obj_data, pass -1 as the offset to
// do a write_full.
void *handle;
- ret = rgwstore->aio_put_obj_data(s->user.user_id, obj,
+ ret = rgwstore->aio_put_obj_data(s->obj_ctx, s->user.user_id, obj,
data,
((ofs == 0) ? -1 : ofs), len, &handle);
if (ret < 0)
if (!multipart) {
rgw_obj dst_obj(s->bucket_str, s->object_str);
- ret = rgwstore->clone_obj(dst_obj, 0, obj, 0, s->obj_size, attrs);
+ ret = rgwstore->clone_obj(s->obj_ctx, dst_obj, 0, obj, 0, s->obj_size, attrs);
if (ret < 0)
goto done_err;
if (created_obj) {
- ret = rgwstore->delete_obj(s->user.user_id, obj);
+ ret = rgwstore->delete_obj(s->obj_ctx, s->user.user_id, obj);
if (ret < 0)
goto done;
}
} else {
- ret = rgwstore->put_obj_meta(s->user.user_id, obj, NULL, attrs, false);
+ ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, obj, NULL, attrs, false);
if (ret < 0)
goto done_err;
rgw_obj meta_obj(s->bucket_str, multipart_meta_obj, s->object_str, mp_ns);
- ret = rgwstore->put_obj_meta(s->user.user_id, meta_obj, NULL, meta_attrs, false);
+ ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, meta_obj, NULL, meta_attrs, false);
}
}
done:
done_err:
if (created_obj)
- rgwstore->delete_obj(s->user.user_id, obj);
+ rgwstore->delete_obj(s->obj_ctx, s->user.user_id, obj);
drain_pending(pending);
send_response();
}
ret = -EINVAL;
rgw_obj obj(s->bucket_str, s->object_str);
if (s->object) {
- ret = rgwstore->delete_obj(s->user.user_id, obj);
+ ret = rgwstore->delete_obj(s->obj_ctx, s->user.user_id, obj);
}
send_response();
src_obj.init(src_bucket, src_object);
dst_obj.init(s->bucket_str, s->object_str);
- ret = rgwstore->copy_obj(s->user.user_id,
+ ret = rgwstore->copy_obj(s->obj_ctx, s->user.user_id,
dst_obj,
src_obj,
&mtime,
new_policy.encode(bl);
obj.init(s->bucket_str, s->object_str);
- ret = rgwstore->set_attr(obj, RGW_ATTR_ACL, bl);
+ ret = rgwstore->set_attr(s->obj_ctx, obj, RGW_ATTR_ACL, bl);
done:
free(orig_data);
tmp_obj_name = mp.get_meta();
obj.init(s->bucket_str, tmp_obj_name, s->object_str, mp_ns);
- ret = rgwstore->put_obj_meta(s->user.user_id, obj, NULL, attrs, true);
+ ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, obj, NULL, attrs, true);
} while (ret == -EEXIST);
done:
send_response();
rgw_obj obj(s->bucket_str, meta_oid, s->object_str, mp_ns);
- int ret = rgwstore->prepare_get_obj(obj, 0, NULL, &attrs, NULL,
+ int ret = rgwstore->prepare_get_obj(s->obj_ctx, obj, 0, NULL, &attrs, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, &handle, &s->err);
rgwstore->finish_get_obj(&handle);
attrs[RGW_ATTR_ETAG] = etag_bl;
target_obj.init(s->bucket_str, s->object_str);
- ret = rgwstore->put_obj_meta(s->user.user_id, target_obj, NULL, attrs, false);
+ ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, target_obj, NULL, attrs, false);
if (ret < 0)
goto done;
ofs += obj_iter->second.size;
}
- ret = rgwstore->clone_objs(target_obj, ranges, attrs, true);
+ ret = rgwstore->clone_objs(s->obj_ctx, target_obj, ranges, attrs, true);
if (ret < 0)
goto done;
for (obj_iter = obj_parts.begin(); obj_iter != obj_parts.end(); ++obj_iter) {
string oid = mp.get_part(obj_iter->second.num);
rgw_obj obj(s->bucket_str, oid, s->object_str, mp_ns);
- rgwstore->delete_obj(s->user.user_id, obj);
+ rgwstore->delete_obj(s->obj_ctx, s->user.user_id, obj);
}
// and also remove the metadata obj
meta_obj.init(s->bucket_str, meta_oid, s->object_str, mp_ns);
- rgwstore->delete_obj(s->user.user_id, meta_obj);
+ rgwstore->delete_obj(s->obj_ctx, s->user.user_id, meta_obj);
done:
send_response();
for (obj_iter = obj_parts.begin(); obj_iter != obj_parts.end(); ++obj_iter) {
string oid = mp.get_part(obj_iter->second.num);
rgw_obj obj(s->bucket_str, oid, s->object_str, mp_ns);
- ret = rgwstore->delete_obj(s->user.user_id, obj);
+ ret = rgwstore->delete_obj(s->obj_ctx, s->user.user_id, obj);
if (ret < 0 && ret != -ENOENT)
goto done;
}
// and also remove the metadata obj
meta_obj.init(s->bucket_str, meta_oid, s->object_str, mp_ns);
- ret = rgwstore->delete_obj(s->user.user_id, meta_obj);
+ ret = rgwstore->delete_obj(s->obj_ctx, s->user.user_id, meta_obj);
if (ret == -ENOENT) {
ret = -ERR_NO_SUCH_BUCKET;
}
#include <errno.h>
#include <stdlib.h>
+#include <sys/types.h>
#include "rgw_access.h"
#include "rgw_rados.h"
* exclusive: create object exclusively
* Returns: 0 on success, -ERR# otherwise.
*/
-int RGWRados::put_obj_meta(std::string& id, rgw_obj& obj,
+int RGWRados::put_obj_meta(void *ctx, std::string& id, rgw_obj& obj,
time_t *mtime, map<string, bufferlist>& attrs, bool exclusive)
{
std::string& bucket = obj.bucket;
* attrs: all the given attrs are written to bucket storage for the given object
* Returns: 0 on success, -ERR# otherwise.
*/
-int RGWRados::put_obj_data(std::string& id, rgw_obj& obj,
+int RGWRados::put_obj_data(void *ctx, std::string& id, rgw_obj& obj,
const char *data, off_t ofs, size_t len)
{
void *handle;
- int r = aio_put_obj_data(id, obj, data, ofs, len, &handle);
+ int r = aio_put_obj_data(ctx, id, obj, data, ofs, len, &handle);
if (r < 0)
return r;
return aio_wait(handle);
}
-int RGWRados::aio_put_obj_data(std::string& id, rgw_obj& obj,
+int RGWRados::aio_put_obj_data(void *ctx, std::string& id, rgw_obj& obj,
const char *data, off_t ofs, size_t len,
void **handle)
{
* err: stores any errors resulting from the get of the original object
* Returns: 0 on success, -ERR# otherwise.
*/
-int RGWRados::copy_obj(std::string& id, rgw_obj& dest_obj,
+int RGWRados::copy_obj(void *ctx, std::string& id, rgw_obj& dest_obj,
rgw_obj& src_obj,
time_t *mtime,
const time_t *mod_ptr,
void *handle = NULL;
map<string, bufferlist> attrset;
- ret = prepare_get_obj(src_obj, 0, &end, &attrset,
+ ret = prepare_get_obj(ctx, src_obj, 0, &end, &attrset,
mod_ptr, unmod_ptr, &lastmod, if_match, if_nomatch, &total_len, &obj_size, &handle, err);
if (ret < 0)
off_t ofs = 0;
do {
- ret = get_obj(&handle, src_obj, &data, ofs, end);
+ ret = get_obj(ctx, &handle, src_obj, &data, ofs, end);
if (ret < 0)
return ret;
// 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(id, tmp_obj, data, ((ofs == 0) ? -1 : ofs), ret);
+ r = put_obj_data(ctx, id, tmp_obj, data, ((ofs == 0) ? -1 : ofs), ret);
free(data);
if (r < 0)
goto done_err;
}
attrs = attrset;
- ret = clone_obj(dest_obj, 0, tmp_obj, 0, end + 1, attrs);
+ ret = clone_obj(ctx, dest_obj, 0, tmp_obj, 0, end + 1, attrs);
if (mtime)
- obj_stat(tmp_obj, NULL, mtime);
+ obj_stat(ctx, tmp_obj, NULL, mtime);
- r = rgwstore->delete_obj(id, tmp_obj, false);
+ r = rgwstore->delete_obj(ctx, id, tmp_obj, false);
if (r < 0)
RGW_LOG(0) << "ERROR: could not remove " << tmp_obj << dendl;
return ret;
done_err:
- rgwstore->delete_obj(id, tmp_obj, false);
+ rgwstore->delete_obj(ctx, id, tmp_obj, false);
finish_get_obj(&handle);
return r;
}
return r;
rgw_obj obj(rgw_root_bucket, bucket);
- r = delete_obj(id, obj, true);
+ r = delete_obj(NULL, id, obj, true);
if (r < 0)
return r;
}
rgw_obj obj(rgw_root_bucket, bucket);
- r = delete_obj(id, obj, true);
+ r = delete_obj(NULL, id, obj, true);
if (r < 0) {
RGW_LOG(0) << "WARNING: could not remove bucket object: " << RGW_ROOT_BUCKET << ":" << bucket << dendl;
ret = r;
* obj: name of the object to delete
* Returns: 0 on success, -ERR# otherwise.
*/
-int RGWRados::delete_obj(std::string& id, rgw_obj& obj, bool sync)
+int RGWRados::delete_obj(void *ctx, std::string& id, rgw_obj& obj, bool sync)
{
std::string& bucket = obj.bucket;
std::string& oid = obj.object;
return 0;
}
+int RGWRados::get_obj_state(RGWRadosCtx *rctx, rgw_obj& obj, librados::IoCtx& io_ctx, string& actual_obj, RGWObjState **state)
+{
+ RGWObjState *s = rctx->get_state(obj);
+ if (s->has_attrs)
+ return 0;
+
+ *state = s;
+
+ int r = io_ctx.getxattrs(actual_obj, s->attrset);
+ if (r < 0)
+ return r;
+
+ s->has_attrs = true;
+ s->ver = io_ctx.get_last_version();
+ return 0;
+}
+
/**
* Get the attributes for an object.
* bucket: name of the bucket holding the object.
* dest: bufferlist to store the result in
* Returns: 0 on success, -ERR# otherwise.
*/
-int RGWRados::get_attr(rgw_obj& obj, const char *name, bufferlist& dest)
+int RGWRados::get_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& dest)
{
std::string& bucket = obj.bucket;
std::string& oid = obj.object;
librados::IoCtx io_ctx;
string actual_bucket = bucket;
string actual_obj = oid;
+ RGWRadosCtx *rctx = (RGWRadosCtx *)ctx;
if (actual_obj.size() == 0) {
actual_obj = bucket;
io_ctx.locator_set_key(obj.key);
+ if (rctx) {
+ RGWObjState *state;
+ r = get_obj_state(rctx, obj, io_ctx, actual_obj, &state);
+ if (r < 0)
+ return r;
+ if (state->get_attr(name, dest))
+ return 0;
+ return -ENODATA;
+ }
+
r = io_ctx.getxattr(actual_obj, name, dest);
if (r < 0)
return r;
* bl: the contents of the attr
* Returns: 0 on success, -ERR# otherwise.
*/
-int RGWRados::set_attr(rgw_obj& obj, const char *name, bufferlist& bl)
+int RGWRados::set_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& bl)
{
std::string& bucket = obj.bucket;
std::string& oid = obj.object;
librados::IoCtx io_ctx;
string actual_bucket = bucket;
string actual_obj = oid;
+ RGWRadosCtx *rctx = (RGWRadosCtx *)ctx;
if (actual_obj.size() == 0) {
actual_obj = bucket;
io_ctx.locator_set_key(obj.key);
- r = io_ctx.setxattr(actual_obj, name, bl);
+ if (rctx) {
+ RGWObjState *state;
+ r = get_obj_state(rctx, obj, io_ctx, actual_obj, &state);
+ if (r < 0)
+ return r;
+ ObjectOperation op;
+ if (state->obj_tag.length() > 0) // check for backward compatibility
+ op.cmpxattr(RGW_ATTR_ID_TAG, state->obj_tag);
+ op.setxattr(name, bl);
+
+ bufferlist outbl;
+ r = io_ctx.operate(actual_obj, &op, &outbl);
+
+ if (r >= 0)
+ state->attrset[name] = bl;
+ } else {
+ r = io_ctx.setxattr(actual_obj, name, bl);
+ }
+
if (r < 0)
return r;
* (if get_data==true) length of read data,
* (if get_data==false) length of the object
*/
-int RGWRados::prepare_get_obj(rgw_obj& obj,
+int RGWRados::prepare_get_obj(void *ctx, rgw_obj& obj,
off_t ofs, off_t *end,
map<string, bufferlist> *attrs,
const time_t *mod_ptr,
}
if (attrs) {
- r = state->io_ctx.getxattrs(oid, *attrs);
+ r = state->io_ctx.getxattrs(oid, *attrs); /* FIXME: should be get_xattrs(), using ctx */
if (g_conf->rgw_log >= 20) {
for (iter = attrs->begin(); iter != attrs->end(); ++iter) {
RGW_LOG(20) << "Read xattr: " << iter->first << dendl;
}
}
if (if_match || if_nomatch) {
- r = get_attr(obj, RGW_ATTR_ETAG, etag);
+ r = get_attr(ctx, obj, RGW_ATTR_ETAG, etag);
if (r < 0)
goto done_err;
return r;
}
-int RGWRados::clone_range(rgw_obj& dst_obj, off_t dst_ofs,
+int RGWRados::clone_range(void *ctx, rgw_obj& dst_obj, off_t dst_ofs,
rgw_obj& src_obj, off_t src_ofs, uint64_t size)
{
std::string& bucket = dst_obj.bucket;
return io_ctx.clone_range(dst_oid, dst_ofs, src_oid, src_ofs, size);
}
-int RGWRados::clone_objs(rgw_obj& dst_obj,
+int RGWRados::clone_objs(void *ctx, rgw_obj& dst_obj,
vector<RGWCloneRangeInfo>& ranges,
map<string, bufferlist> attrs,
bool truncate_dest)
return ret;
}
-int RGWRados::get_obj(void **handle, rgw_obj& obj,
+int RGWRados::get_obj(void *ctx, void **handle, rgw_obj& obj,
char **data, off_t ofs, off_t end)
{
std::string& oid = obj.object;
}
/* a simple object read */
-int RGWRados::read(rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl)
+int RGWRados::read(void *ctx, rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl)
{
std::string& bucket = obj.bucket;
std::string& oid = obj.object;
return r;
}
-int RGWRados::obj_stat(rgw_obj& obj, uint64_t *psize, time_t *pmtime)
+int RGWRados::obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime)
{
std::string& bucket = obj.bucket;
std::string& oid = obj.object;
class RGWWatcher;
+struct RGWObjState {
+ bool is_atomic;
+ uint64_t ver;
+ bool has_attrs;
+ bufferlist obj_tag;
+
+ map<string, bufferlist> attrset;
+ RGWObjState() : is_atomic(false), ver(0), has_attrs(0) {}
+
+ bool get_attr(string name, bufferlist& dest) {
+ map<string, bufferlist>::iterator iter = attrset.find(name);
+ if (iter != attrset.end()) {
+ dest = iter->second;
+ return true;
+ }
+ return false;
+ }
+};
+
+struct RGWRadosCtx {
+ map<rgw_obj, RGWObjState> objs_state;
+ RGWObjState *get_state(rgw_obj& obj) {
+ return &objs_state[obj];
+ }
+};
+
class RGWRados : public RGWAccess
{
/** Open the pool used as root for this gateway */
librados::IoCtx root_pool_ctx;
librados::IoCtx control_pool_ctx;
+ int get_obj_state(RGWRadosCtx *rctx, rgw_obj& obj, librados::IoCtx& io_ctx, string& actual_obj, RGWObjState **state);
public:
RGWRados() : watcher(NULL), watch_handle(0) {}
virtual int create_bucket(std::string& id, std::string& bucket, map<std::string,bufferlist>& attrs, bool exclusive = true, uint64_t auid = 0);
/** Write/overwrite an object to the bucket storage. */
- virtual int put_obj_meta(std::string& id, rgw_obj& obj, time_t *mtime,
+ virtual int put_obj_meta(void *ctx, std::string& id, rgw_obj& obj, time_t *mtime,
map<std::string, bufferlist>& attrs, bool exclusive);
- virtual int put_obj_data(std::string& id, rgw_obj& obj, const char *data,
+ virtual int put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data,
off_t ofs, size_t len);
- virtual int aio_put_obj_data(std::string& id, rgw_obj& obj, const char *data,
+ virtual int aio_put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data,
off_t ofs, size_t len, void **handle);
virtual int aio_wait(void *handle);
virtual bool aio_completed(void *handle);
- virtual int clone_range(rgw_obj& dst_obj, off_t dst_ofs,
+ virtual int clone_range(void *ctx, rgw_obj& dst_obj, off_t dst_ofs,
rgw_obj& src_obj, off_t src_ofs, uint64_t size);
- virtual int clone_objs(rgw_obj& dst_obj,
+ virtual int clone_objs(void *ctx, rgw_obj& dst_obj,
vector<RGWCloneRangeInfo>& ranges,
map<string, bufferlist> attrs, bool truncate_dest);
/** Copy an object, with many extra options */
- virtual int copy_obj(std::string& id, rgw_obj& dest_obj,
+ virtual int copy_obj(void *ctx, std::string& id, rgw_obj& dest_obj,
rgw_obj& src_obj,
time_t *mtime,
const time_t *mod_ptr,
virtual int bucket_suspended(std::string& bucket, bool *suspended);
/** Delete an object.*/
- virtual int delete_obj(std::string& id, rgw_obj& src_obj, bool sync);
+ virtual int delete_obj(void *ctx, std::string& id, rgw_obj& src_obj, bool sync);
/** Get the attributes for an object.*/
- virtual int get_attr(rgw_obj& obj, const char *name, bufferlist& dest);
+ virtual int get_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& dest);
/** Set an attr on an object. */
- virtual int set_attr(rgw_obj& obj, const char *name, bufferlist& bl);
+ virtual int set_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& bl);
/** Get data about an object out of RADOS and into memory. */
- virtual int prepare_get_obj(rgw_obj& obj,
+ virtual int prepare_get_obj(void *ctx, rgw_obj& obj,
off_t ofs, off_t *end,
map<string, bufferlist> *attrs,
const time_t *mod_ptr,
void **handle,
struct rgw_err *err);
- virtual int get_obj(void **handle, rgw_obj& obj,
+ virtual int get_obj(void *ctx, void **handle, rgw_obj& obj,
char **data, off_t ofs, off_t end);
virtual void finish_get_obj(void **handle);
- virtual int read(rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl);
+ virtual int read(void *ctx, rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl);
- virtual int obj_stat(rgw_obj& obj, uint64_t *psize, time_t *pmtime);
+ virtual int obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime);
virtual int get_bucket_id(std::string& bucket);
virtual void finalize_watch();
virtual int distribute(bufferlist& bl);
virtual int watch_cb(int opcode, uint64_t ver, bufferlist& bl) { return 0; }
+
+ void *create_context() {
+ return new RGWRadosCtx();
+ }
+ void destroy_context(void *ctx) {
+ delete (RGWRadosCtx *)ctx;
+ }
+
+ void set_atomic_ops(void *ctx, rgw_obj& obj);
};
#endif
rgw_obj obj(bucket, oid);
- int ret = rgwstore->put_obj(uid, obj, data, size, NULL, attrs);
+ int ret = rgwstore->put_obj(NULL, uid, obj, data, size, NULL, attrs);
if (ret == -ENOENT) {
ret = rgwstore->create_bucket(uid, bucket, attrs);
if (ret >= 0)
- ret = rgwstore->put_obj(uid, obj, data, size, NULL, attrs);
+ ret = rgwstore->put_obj(NULL, uid, obj, data, size, NULL, attrs);
}
return ret;
bufferlist::iterator iter;
int request_len = READ_CHUNK_LEN;
rgw_obj obj(bucket, key);
- ret = rgwstore->prepare_get_obj(obj, 0, NULL, NULL, NULL,
+ ret = rgwstore->prepare_get_obj(NULL, obj, 0, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, &handle, &err);
if (ret < 0)
return ret;
do {
- ret = rgwstore->get_obj(&handle, obj, &data, 0, request_len - 1);
+ ret = rgwstore->get_obj(NULL, &handle, obj, &data, 0, request_len - 1);
if (ret < 0)
goto done;
if (ret < request_len)
{
bufferlist bl;
rgw_obj obj(ui_uid_bucket, user_id);
- int ret = rgwstore->get_attr(obj, RGW_ATTR_BUCKETS, bl);
+ int ret = rgwstore->get_attr(NULL, obj, RGW_ATTR_BUCKETS, bl);
if (ret)
return ret;
rgw_obj obj(ui_uid_bucket, buckets_obj_id);
do {
- ret = rgwstore->read(obj, 0, len, bl);
+ ret = rgwstore->read(NULL, obj, 0, len, bl);
if (ret == -ENOENT) {
/* try to read the old format */
ret = rgw_read_buckets_from_attr(user_id, buckets);
rgw_obj obj(ui_uid_bucket, user_id);
- int ret = rgwstore->set_attr(obj, RGW_ATTR_BUCKETS, bl);
+ int ret = rgwstore->set_attr(NULL, obj, RGW_ATTR_BUCKETS, bl);
return ret;
}
int rgw_remove_key_index(RGWAccessKey& access_key)
{
rgw_obj obj(ui_key_bucket, access_key.id);
- int ret = rgwstore->delete_obj(access_key.id, obj);
+ int ret = rgwstore->delete_obj(NULL, access_key.id, obj);
return ret;
}
int rgw_remove_uid_index(string& uid)
{
rgw_obj obj(ui_uid_bucket, uid);
- int ret = rgwstore->delete_obj(uid, obj);
+ int ret = rgwstore->delete_obj(NULL, uid, obj);
return ret;
}
int rgw_remove_email_index(string& uid, string& email)
{
rgw_obj obj(ui_email_bucket, email);
- int ret = rgwstore->delete_obj(uid, obj);
+ int ret = rgwstore->delete_obj(NULL, uid, obj);
return ret;
}
int rgw_remove_openstack_name_index(string& uid, string& openstack_name)
{
rgw_obj obj(ui_openstack_bucket, openstack_name);
- int ret = rgwstore->delete_obj(uid, obj);
+ int ret = rgwstore->delete_obj(NULL, uid, obj);
return ret;
}
}
rgw_obj uid_obj(ui_uid_bucket, info.user_id);
- ret = rgwstore->delete_obj(info.user_id, uid_obj);
+ ret = rgwstore->delete_obj(NULL, info.user_id, uid_obj);
if (ret < 0 && ret != -ENOENT)
RGW_LOG(0) << "ERROR: could not remove " << info.user_id << ":" << uid_obj << ", should be fixed manually (err=" << ret << ")" << dendl;
string buckets_obj_id;
get_buckets_obj(info.user_id, buckets_obj_id);
rgw_obj uid_bucks(ui_uid_bucket, buckets_obj_id);
- ret = rgwstore->delete_obj(info.user_id, uid_bucks);
+ ret = rgwstore->delete_obj(NULL, info.user_id, uid_bucks);
if (ret < 0 && ret != -ENOENT)
RGW_LOG(0) << "ERROR: could not remove " << info.user_id << ":" << uid_bucks << ", should be fixed manually (err=" << ret << ")" << dendl;
rgw_obj email_obj(ui_email_bucket, info.user_email);
- ret = rgwstore->delete_obj(info.user_id, email_obj);
+ ret = rgwstore->delete_obj(NULL, info.user_id, email_obj);
if (ret < 0 && ret != -ENOENT)
RGW_LOG(0) << "ERROR: could not remove " << info.user_id << ":" << email_obj << ", should be fixed manually (err=" << ret << ")" << dendl;