* exclusive: create object exclusively
* Returns: 0 on success, -ERR# otherwise.
*/
-int RGWRados::Object::Write::write_meta(uint64_t size, uint64_t accounted_size,
- map<string, bufferlist>& attrs)
+int RGWRados::Object::Write::_do_write_meta(uint64_t size, uint64_t accounted_size,
+ map<string, bufferlist>& attrs, bool assume_noent)
{
rgw_bucket bucket;
rgw_rados_ref ref;
ObjectWriteOperation op;
RGWObjState *state;
- int r = target->get_state(&state, false);
+ int r = target->get_state(&state, false, assume_noent);
if (r < 0)
return r;
if (r < 0) { /* we can expect to get -ECANCELED if object was replaced under,
or -ENOENT if was removed, or -EEXIST if it did not exist
before and now it does */
+ if (r == -EEXIST && assume_noent) {
+ target->invalidate_state();
+ return r;
+ }
goto done_cancel;
}
* should treat it as a success
*/
if (meta.if_match == NULL && meta.if_nomatch == NULL) {
- if (r == -ECANCELED || r == -ENOENT || r == -EEXIST) {
+ if (r == -ECANCELED || r == -ENOENT ||
+ (r == -EEXIST && !assume_noent)) /* if assume_noent, we want to send back error so that
+ * we'd be called again with assume_noent == false
+ */ {
r = 0;
}
} else {
return r;
}
+int RGWRados::Object::Write::write_meta(uint64_t size, uint64_t accounted_size,
+ map<string, bufferlist>& attrs)
+{
+ bool assume_noent = (meta.if_match == NULL && meta.if_nomatch == NULL);
+ int r;
+ if (assume_noent) {
+ r = _do_write_meta(size, accounted_size, attrs, assume_noent);
+ if (r == -EEXIST) {
+ assume_noent = false;
+ }
+ }
+ if (!assume_noent) {
+ r = _do_write_meta(size, accounted_size, attrs, assume_noent);
+ }
+ return r;
+}
+
/** Write/overwrite a system object. */
int RGWRados::put_system_obj_impl(rgw_obj& obj, uint64_t size, real_time *mtime,
map<std::string, bufferlist>& attrs, int flags,
return ret;
}
-int RGWRados::get_obj_state_impl(RGWObjectCtx *rctx, rgw_obj& obj, RGWObjState **state, bool follow_olh)
+int RGWRados::get_obj_state_impl(RGWObjectCtx *rctx, rgw_obj& obj, RGWObjState **state, bool follow_olh, bool assume_noent)
{
bool need_follow_olh = follow_olh && !obj.have_instance();
s->obj = obj;
- int r = RGWRados::raw_obj_stat(obj, &s->size, &s->mtime, &s->epoch, &s->attrset, (s->prefetch_data ? &s->data : NULL), NULL);
+ int r = -ENOENT;
+
+ if (!assume_noent) {
+ r = RGWRados::raw_obj_stat(obj, &s->size, &s->mtime, &s->epoch, &s->attrset, (s->prefetch_data ? &s->data : NULL), NULL);
+ }
if (r == -ENOENT) {
s->exists = false;
s->has_attrs = true;
return 0;
}
-int RGWRados::get_obj_state(RGWObjectCtx *rctx, rgw_obj& obj, RGWObjState **state, bool follow_olh)
+int RGWRados::get_obj_state(RGWObjectCtx *rctx, rgw_obj& obj, RGWObjState **state, bool follow_olh, bool assume_noent)
{
int ret;
do {
- ret = get_obj_state_impl(rctx, obj, state, follow_olh);
+ ret = get_obj_state_impl(rctx, obj, state, follow_olh, assume_noent);
} while (ret == -EAGAIN);
return ret;
return 0;
}
-int RGWRados::Object::get_state(RGWObjState **pstate, bool follow_olh)
+int RGWRados::Object::get_state(RGWObjState **pstate, bool follow_olh, bool assume_noent)
{
- return store->get_obj_state(&ctx, obj, pstate, follow_olh);
+ return store->get_obj_state(&ctx, obj, pstate, follow_olh, assume_noent);
}
void RGWRados::Object::invalidate_state()
int get_olh_target_state(RGWObjectCtx& rctx, rgw_obj& obj, RGWObjState *olh_state,
RGWObjState **target_state);
int get_system_obj_state_impl(RGWObjectCtx *rctx, rgw_obj& obj, RGWObjState **state, RGWObjVersionTracker *objv_tracker);
- int get_obj_state_impl(RGWObjectCtx *rctx, rgw_obj& obj, RGWObjState **state, bool follow_olh);
+ int get_obj_state_impl(RGWObjectCtx *rctx, rgw_obj& obj, RGWObjState **state, bool follow_olh, bool assume_noent = false);
int append_atomic_test(RGWObjectCtx *rctx, rgw_obj& obj,
librados::ObjectOperation& op, RGWObjState **state);
bool bs_initialized;
protected:
- int get_state(RGWObjState **pstate, bool follow_olh);
+ int get_state(RGWObjState **pstate, bool follow_olh, bool assume_noent = false);
void invalidate_state();
int prepare_atomic_modification(librados::ObjectWriteOperation& op, bool reset_obj, const string *ptag,
explicit Write(RGWRados::Object *_target) : target(_target) {}
+ int _do_write_meta(uint64_t size, uint64_t accounted_size,
+ map<std::string, bufferlist>& attrs,
+ bool assume_noent);
int write_meta(uint64_t size, uint64_t accounted_size,
map<std::string, bufferlist>& attrs);
int write_data(const char *data, uint64_t ofs, uint64_t len, bool exclusive);
map<string, bufferlist>* rmattrs);
int get_system_obj_state(RGWObjectCtx *rctx, rgw_obj& obj, RGWObjState **state, RGWObjVersionTracker *objv_tracker);
- int get_obj_state(RGWObjectCtx *rctx, rgw_obj& obj, RGWObjState **state, bool follow_olh);
+ int get_obj_state(RGWObjectCtx *rctx, rgw_obj& obj, RGWObjState **state, bool follow_olh, bool assume_noent = false);
int get_obj_state(RGWObjectCtx *rctx, rgw_obj& obj, RGWObjState **state) {
return get_obj_state(rctx, obj, state, true);
}