uint64_t get_size() { return _size; }
real_time ctime() { return mod_time; } // XXX
real_time mtime() { return mod_time; }
- std::map<string, bufferlist>& get_attrs() { return attrs; }
+ std::map<string, bufferlist>& get_attrs() { return attrs.attrs; }
buffer::list* get_attr(const std::string& k) {
auto iter = attrs.find(k);
rgw_bucket_object_pre_exec(s);
}
-static bool object_is_expired(map<string, bufferlist>& attrs) {
- map<string, bufferlist>::iterator iter = attrs.find(RGW_ATTR_DELETE_AT);
- if (iter != attrs.end()) {
- utime_t delete_at;
- try {
- decode(delete_at, iter->second);
- } catch (buffer::error& err) {
- dout(0) << "ERROR: " << __func__ << ": failed to decode " RGW_ATTR_DELETE_AT " attr" << dendl;
- return false;
- }
-
- if (delete_at <= ceph_clock_now() && !delete_at.is_zero()) {
- return true;
- }
- }
-
- return false;
-}
-
static inline void rgw_cond_decode_objtags(
struct req_state *s,
const std::map<std::string, buffer::list> &attrs)
perfcounter->inc(l_rgw_get);
RGWRados::Object op_target(store->getRados(), s->bucket->get_info(), *static_cast<RGWObjectCtx *>(s->obj_ctx), s->object->get_obj());
- RGWRados::Object::Read read_op(&op_target);
+ std::unique_ptr<rgw::sal::RGWObject::ReadOp> read_op(s->object->get_read_op(s->obj_ctx));
op_ret = get_params();
if (op_ret < 0)
if (op_ret < 0)
goto done_err;
- read_op.conds.mod_ptr = mod_ptr;
- read_op.conds.unmod_ptr = unmod_ptr;
- read_op.conds.high_precision_time = s->system_request; /* system request need to use high precision time */
- read_op.conds.mod_zone_id = mod_zone_id;
- read_op.conds.mod_pg_ver = mod_pg_ver;
- read_op.conds.if_match = if_match;
- read_op.conds.if_nomatch = if_nomatch;
- read_op.params.attrs = &attrs;
- read_op.params.lastmod = &lastmod;
- read_op.params.obj_size = &s->obj_size;
+ read_op->params.mod_ptr = mod_ptr;
+ read_op->params.unmod_ptr = unmod_ptr;
+ read_op->params.high_precision_time = s->system_request; /* system request need to use high precision time */
+ read_op->params.mod_zone_id = mod_zone_id;
+ read_op->params.mod_pg_ver = mod_pg_ver;
+ read_op->params.if_match = if_match;
+ read_op->params.if_nomatch = if_nomatch;
+ read_op->params.lastmod = &lastmod;
- op_ret = read_op.prepare(s->yield);
+ op_ret = read_op->prepare(s->yield);
if (op_ret < 0)
goto done_err;
- version_id = read_op.state.obj.key.instance;
- s->object->set_obj_size(s->obj_size);
+ version_id = s->object->get_instance();
+ s->obj_size = s->object->get_obj_size();
+ attrs = s->object->get_attrs();
/* STAT ops don't need data, and do no i/o */
if (get_type() == RGW_OP_STAT_OBJ) {
}
torrent.init(s, store);
rgw_obj obj = s->object->get_obj();
- op_ret = torrent.get_torrent_file(read_op, total_len, bl, obj);
+ op_ret = torrent.get_torrent_file(s->object.get(), total_len, bl, obj);
if (op_ret < 0)
{
ldpp_dout(this, 0) << "ERROR: failed to get_torrent_file ret= " << op_ret
}
/* end gettorrent */
- op_ret = rgw_compression_info_from_attrset(attrs, need_decompress, cs_info);
+ op_ret = rgw_compression_info_from_attrset(attrs.attrs, need_decompress, cs_info);
if (op_ret < 0) {
ldpp_dout(s, 0) << "ERROR: failed to decode compression info, cannot decompress" << dendl;
goto done_err;
goto done_err;
}
- op_ret = read_op.range_to_ofs(s->obj_size, ofs, end);
+ op_ret = s->object->range_to_ofs(s->obj_size, ofs, end);
if (op_ret < 0)
goto done_err;
total_len = (ofs <= end ? end + 1 - ofs : 0);
/* Check whether the object has expired. Swift API documentation
* stands that we should return 404 Not Found in such case. */
- if (need_object_expiration() && object_is_expired(attrs)) {
+ if (need_object_expiration() && s->object->is_expired()) {
op_ret = -ENOENT;
goto done_err;
}
/* Decode S3 objtags, if any */
- rgw_cond_decode_objtags(s, attrs);
+ rgw_cond_decode_objtags(s, attrs.attrs);
start = ofs;
ofs_x = ofs;
end_x = end;
filter->fixup_range(ofs_x, end_x);
- op_ret = read_op.iterate(ofs_x, end_x, filter, s->yield);
+ op_ret = read_op->iterate(ofs_x, end_x, filter, s->yield);
if (op_ret >= 0)
op_ret = filter->flush();
/* Check whether the object has expired. Swift API documentation
* stands that we should return 404 Not Found in such case. */
- if (need_object_expiration() && object_is_expired(s->object->get_attrs().attrs)) {
+ if (need_object_expiration() && s->object->is_expired()) {
op_ret = -ENOENT;
return;
}
/* Check whether the object has expired. Swift API documentation
* stands that we should return 404 Not Found in such case. */
- if (need_object_expiration() && object_is_expired(attrs.attrs)) {
+ if (need_object_expiration() && s->object->is_expired()) {
op_ret = -ENOENT;
return;
}
ceph::real_time unmod_time;
ceph::real_time *mod_ptr;
ceph::real_time *unmod_ptr;
- map<string, bufferlist> attrs;
+ rgw::sal::RGWAttrs attrs;
bool get_data;
bool partial_content;
bool ignore_invalid_range;
friend class RGWBucketReshardLock;
friend class BucketIndexLockGuard;
friend class RGWCompleteMultipart;
+ friend class rgw::sal::RGWRadosStore;
/** Open the pool used as root for this gateway */
int open_root_pool_ctx();
// This field represents the number of bucket index object shards
uint32_t bucket_index_max_shards;
- int get_obj_head_ioctx(const RGWBucketInfo& bucket_info, const rgw_obj& obj, librados::IoCtx *ioctx);
int get_obj_head_ref(const RGWBucketInfo& bucket_info, const rgw_obj& obj, rgw_rados_ref *ref);
int get_system_obj_ref(const rgw_raw_obj& obj, rgw_rados_ref *ref);
uint64_t max_bucket_id;
RGWIndexCompletionManager *index_completion_manager{nullptr};
bool use_cache{false};
+
+ int get_obj_head_ioctx(const RGWBucketInfo& bucket_info, const rgw_obj& obj, librados::IoCtx *ioctx);
public:
RGWRados(): timer(NULL),
gc(NULL), lc(NULL), obj_expirer(NULL), use_gc_thread(false), use_lc_thread(false), quota_threads(false),
/* JSON encode object metadata */
JSONFormatter jf;
jf.open_object_section("obj_metadata");
- encode_json("attrs", attrs, &jf);
+ encode_json("attrs", attrs.attrs, &jf);
utime_t ut(lastmod);
encode_json("mtime", ut, &jf);
jf.close_section();
/* we end up dumping mtime in two different methods, a bit redundant */
dump_epoch_header(s, "Rgwx-Mtime", lastmod);
uint64_t pg_ver = 0;
- int r = decode_attr_bl_single_value(attrs, RGW_ATTR_PG_VER, &pg_ver, (uint64_t)0);
+ int r = decode_attr_bl_single_value(attrs.attrs, RGW_ATTR_PG_VER, &pg_ver, (uint64_t)0);
if (r < 0) {
ldpp_dout(this, 0) << "ERROR: failed to decode pg ver attr, ignoring" << dendl;
}
dump_header(s, "Rgwx-Obj-PG-Ver", pg_ver);
uint32_t source_zone_short_id = 0;
- r = decode_attr_bl_single_value(attrs, RGW_ATTR_SOURCE_ZONE, &source_zone_short_id, (uint32_t)0);
+ r = decode_attr_bl_single_value(attrs.attrs, RGW_ATTR_SOURCE_ZONE, &source_zone_short_id, (uint32_t)0);
if (r < 0) {
ldpp_dout(this, 0) << "ERROR: failed to decode pg ver attr, ignoring" << dendl;
}
int res = 0;
std::unique_ptr<BlockCrypt> block_crypt;
- res = rgw_s3_prepare_decrypt(s, attrs, &block_crypt, crypt_http_responses);
+ res = rgw_s3_prepare_decrypt(s, attrs.attrs, &block_crypt, crypt_http_responses);
if (res == 0) {
if (block_crypt != nullptr) {
auto f = std::make_unique<RGWGetObj_BlockDecrypt>(s->cct, cb, std::move(block_crypt));
}
}
- get_contype_from_attrs(attrs, content_type);
- dump_object_metadata(this, s, attrs);
+ get_contype_from_attrs(attrs.attrs, content_type);
+ dump_object_metadata(this, s, attrs.attrs);
}
end_header(s, this, !content_type.empty() ? content_type.c_str()
rados->finalize();
}
+int RGWObject::range_to_ofs(uint64_t obj_size, int64_t &ofs, int64_t &end)
+{
+ if (ofs < 0) {
+ ofs += obj_size;
+ if (ofs < 0)
+ ofs = 0;
+ end = obj_size - 1;
+ } else if (end < 0) {
+ end = obj_size - 1;
+ }
+
+ if (obj_size > 0) {
+ if (ofs >= (off_t)obj_size) {
+ return -ERANGE;
+ }
+ if (end >= (off_t)obj_size) {
+ end = obj_size - 1;
+ }
+ }
+ return 0;
+}
+
int RGWRadosObject::get_obj_state(RGWObjectCtx *rctx, RGWBucket& bucket, RGWObjState **state, optional_yield y, bool follow_olh)
{
rgw_obj obj(bucket.get_bi(), key.name);
store->getRados()->set_prefetch_data(rctx, obj);
}
+bool RGWRadosObject::is_expired() {
+ map<string, bufferlist>::iterator iter = attrs.find(RGW_ATTR_DELETE_AT);
+ if (iter != attrs.end()) {
+ utime_t delete_at;
+ try {
+ auto bufit = iter->second.cbegin();
+ decode(delete_at, bufit);
+ } catch (buffer::error& err) {
+ ldout(store->ctx(), 0) << "ERROR: " << __func__ << ": failed to decode " RGW_ATTR_DELETE_AT " attr" << dendl;
+ return false;
+ }
+
+ if (delete_at <= ceph_clock_now() && !delete_at.is_zero()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
void RGWRadosObject::gen_rand_obj_instance_name()
{
store->getRados()->gen_rand_obj_instance_name(&key);
}
+int RGWRadosObject::omap_get_vals_by_keys(const std::string& oid,
+ const std::set<std::string>& keys,
+ std::map<std::string, bufferlist> *vals)
+{
+ int ret;
+ rgw_raw_obj head_obj;
+ librados::IoCtx cur_ioctx;
+ rgw_obj obj = get_obj();
+
+ store->getRados()->obj_to_raw(bucket->get_placement_rule(), obj, &head_obj);
+ ret = store->get_obj_head_ioctx(bucket->get_info(), obj, &cur_ioctx);
+ if (ret < 0) {
+ return ret;
+ }
+
+ return cur_ioctx.omap_get_vals_by_keys(oid, keys, vals);
+}
+
+RGWObject::ReadOp* RGWRadosObject::get_read_op(RGWObjectCtx *ctx)
+{
+ return new RGWRadosObject::RadosReadOp(this, ctx);
+}
+
+RGWRadosObject::RadosReadOp::RadosReadOp(RGWRadosObject *_source, RGWObjectCtx *_rctx) :
+ source(_source),
+ rctx(_rctx),
+ op_target(_source->store->getRados(),
+ _source->get_bucket()->get_info(),
+ *static_cast<RGWObjectCtx *>(rctx),
+ _source->get_obj()),
+ parent_op(&op_target)
+{ }
+
+int RGWRadosObject::RadosReadOp::prepare(optional_yield y)
+{
+ uint64_t obj_size;
+
+ parent_op.conds.mod_ptr = params.mod_ptr;
+ parent_op.conds.unmod_ptr = params.unmod_ptr;
+ parent_op.conds.high_precision_time = params.high_precision_time;
+ parent_op.conds.mod_zone_id = params.mod_zone_id;
+ parent_op.conds.mod_pg_ver = params.mod_pg_ver;
+ parent_op.conds.if_match = params.if_match;
+ parent_op.conds.if_nomatch = params.if_nomatch;
+ parent_op.params.lastmod = params.lastmod;
+ parent_op.params.target_obj = params.target_obj;
+ parent_op.params.obj_size = &obj_size;
+ parent_op.params.attrs = &source->get_attrs().attrs;
+
+ int ret = parent_op.prepare(y);
+ if (ret < 0)
+ return ret;
+
+ source->set_key(parent_op.state.obj.key);
+ source->set_obj_size(obj_size);
+
+ return ret;
+}
+
+int RGWRadosObject::RadosReadOp::read(int64_t ofs, int64_t end, bufferlist& bl, optional_yield y)
+{
+ return parent_op.read(ofs, end, bl, y);
+}
+
+int RGWRadosObject::RadosReadOp::iterate(int64_t ofs, int64_t end, RGWGetDataCB *cb, optional_yield y)
+{
+ return parent_op.iterate(ofs, end, cb, y);
+}
+
int RGWRadosStore::get_bucket(RGWUser* u, const rgw_bucket& b, std::unique_ptr<RGWBucket>* bucket)
{
int ret;
return store;
}
+int rgw::sal::RGWRadosStore::get_obj_head_ioctx(const RGWBucketInfo& bucket_info, const rgw_obj& obj, librados::IoCtx *ioctx)
+{
+ return rados->get_obj_head_ioctx(bucket_info, obj, ioctx);
+}
+
void RGWStoreManager::close_storage(rgw::sal::RGWRadosStore *store)
{
if (!store)
void emplace(std::string&& key, buffer::list&& bl) {
attrs.emplace(std::move(key), std::move(bl)); /* key and bl are r-value refs */
+ map<string, bufferlist>::iterator find(const std::string& key);
}
std::map<std::string, bufferlist>::iterator find(const std::string& key) {
return attrs.find(key);
}
+ std::map<std::string, bufferlist>::iterator end() {
+ return attrs.end();
+ }
+ std::map<std::string, bufferlist>::iterator begin() {
+ return attrs.begin();
+ }
};
class RGWStore : public DoutPrefixProvider {
RGWBucket* bucket;
std::string index_hash_source;
uint64_t obj_size;
+ RGWAttrs attrs;
ceph::real_time mtime;
public:
- RGWObject() : key(), bucket(nullptr), index_hash_source(), obj_size(), mtime() {}
- RGWObject(const rgw_obj_key& _k) : key(_k), bucket(), index_hash_source(), obj_size(), mtime() {}
- RGWObject(const rgw_obj_key& _k, RGWBucket* _b) : key(_k), bucket(_b), index_hash_source(), obj_size(), mtime() {}
- RGWObject(const RGWObject& _o) = default;
+
+ struct ReadOp {
+ struct Params {
+ const ceph::real_time *mod_ptr{nullptr};
+ const ceph::real_time *unmod_ptr{nullptr};
+ bool high_precision_time{false};
+ uint32_t mod_zone_id{0};
+ uint64_t mod_pg_ver{0};
+ const char *if_match{nullptr};
+ const char *if_nomatch{nullptr};
+ ceph::real_time *lastmod{nullptr};
+ rgw_obj *target_obj{nullptr}; // XXX dang remove?
+ } params;
+
+ virtual ~ReadOp() = default;
+
+ virtual int prepare(optional_yield y) = 0;
+ virtual int read(int64_t ofs, int64_t end, bufferlist& bl, optional_yield y) = 0;
+ virtual int iterate(int64_t ofs, int64_t end, RGWGetDataCB *cb, optional_yield y) = 0;
+ };
+
+ RGWObject()
+ : key(),
+ bucket(nullptr),
+ index_hash_source(),
+ obj_size(),
+ attrs(),
+ mtime() {}
+ RGWObject(const rgw_obj_key& _k)
+ : key(_k),
+ bucket(),
+ index_hash_source(),
+ obj_size(),
+ attrs(),
+ mtime() {}
+ RGWObject(const rgw_obj_key& _k, RGWBucket* _b)
+ : key(_k),
+ bucket(_b),
+ index_hash_source(),
+ obj_size(),
+ attrs(),
+ mtime() {}
+ RGWObject(RGWObject& _o) = default;
virtual ~RGWObject() = default;
virtual int read(off_t offset, off_t length, std::iostream& stream) = 0;
virtual int write(off_t offset, off_t length, std::iostream& stream) = 0;
- virtual RGWAttrs& get_attrs(void) = 0;
virtual int delete_object(void) = 0;
virtual RGWAccessControlPolicy& get_acl(void) = 0;
virtual int set_acl(const RGWAccessControlPolicy& acl) = 0;
virtual int modify_obj_attrs(RGWObjectCtx *rctx, const char *attr_name, bufferlist& attr_val, optional_yield y) = 0;
virtual int delete_obj_attrs(RGWObjectCtx *rctx, const char *attr_name, optional_yield y) = 0;
virtual int copy_obj_data(RGWObjectCtx& rctx, RGWBucket* dest_bucket, RGWObject* dest_obj, uint16_t olh_epoch, std::string* petag, const DoutPrefixProvider *dpp, optional_yield y) = 0;
+ virtual bool is_expired() = 0;
+ RGWAttrs& get_attrs(void) { return attrs; }
ceph::real_time get_mtime(void) const { return mtime; }
uint64_t get_obj_size(void) const { return obj_size; }
RGWBucket* get_bucket(void) const { return bucket; }
std::string get_hash_source(void) { return index_hash_source; }
void set_hash_source(std::string s) { index_hash_source = s; }
std::string get_oid(void) const { return key.get_oid(); }
+ int range_to_ofs(uint64_t obj_size, int64_t &ofs, int64_t &end);
+
+ /* OPs */
+ virtual ReadOp* get_read_op(RGWObjectCtx *) = 0;
+
+ /* OMAP */
+ virtual int omap_get_vals_by_keys(const std::string& oid,
+ const std::set<std::string>& keys,
+ std::map<std::string, bufferlist> *vals) = 0;
static bool empty(RGWObject* o) { return (!o || o->empty()); }
virtual std::unique_ptr<RGWObject> clone() = 0;
class RGWRadosObject : public RGWObject {
private:
RGWRadosStore *store;
- RGWAttrs attrs;
RGWAccessControlPolicy acls;
public:
- RGWRadosObject()
- : store(),
- attrs(),
- acls() {
- }
+ struct RadosReadOp : public ReadOp {
+ private:
+ RGWRadosObject* source;
+ RGWObjectCtx* rctx;
+ RGWRados::Object op_target;
+ RGWRados::Object::Read parent_op;
+
+ public:
+ RadosReadOp(RGWRadosObject *_source, RGWObjectCtx *_rctx);
+
+ virtual int prepare(optional_yield y) override;
+ virtual int read(int64_t ofs, int64_t end, bufferlist& bl, optional_yield y) override;
+ virtual int iterate(int64_t ofs, int64_t end, RGWGetDataCB *cb, optional_yield y) override;
+ };
+
+ RGWRadosObject() = default;
RGWRadosObject(RGWRadosStore *_st, const rgw_obj_key& _k)
: RGWObject(_k),
store(_st),
- attrs(),
acls() {
}
RGWRadosObject(RGWRadosStore *_st, const rgw_obj_key& _k, RGWBucket* _b)
: RGWObject(_k, _b),
store(_st),
- attrs(),
acls() {
}
- RGWRadosObject(const RGWRadosObject& _o) = default;
+ RGWRadosObject(RGWRadosObject& _o) = default;
int read(off_t offset, off_t length, std::iostream& stream) { return length; }
int write(off_t offset, off_t length, std::iostream& stream) { return length; }
- RGWAttrs& get_attrs(void) { return attrs; }
int delete_object(void) { return 0; }
RGWAccessControlPolicy& get_acl(void) { return acls; }
int set_acl(const RGWAccessControlPolicy& acl) { acls = acl; return 0; }
virtual int modify_obj_attrs(RGWObjectCtx *rctx, const char *attr_name, bufferlist& attr_val, optional_yield y) override;
virtual int delete_obj_attrs(RGWObjectCtx *rctx, const char *attr_name, optional_yield y) override;
virtual int copy_obj_data(RGWObjectCtx& rctx, RGWBucket* dest_bucket, RGWObject* dest_obj, uint16_t olh_epoch, std::string* petag, const DoutPrefixProvider *dpp, optional_yield y) override;
+ virtual bool is_expired() override;
virtual void gen_rand_obj_instance_name() override;
virtual std::unique_ptr<RGWObject> clone() {
return std::unique_ptr<RGWObject>(new RGWRadosObject(*this));
}
+ /* OPs */
+ virtual ReadOp* get_read_op(RGWObjectCtx *) override;
+
+ /* OMAP */
+ virtual int omap_get_vals_by_keys(const std::string& oid,
+ const std::set<std::string>& keys,
+ std::map<std::string, bufferlist> *vals) override;
+
private:
int read_attrs(RGWRados::Object::Read &read_op, optional_yield y, rgw_obj *target_obj = nullptr);
};
virtual CephContext *ctx(void) { return rados->ctx(); }
+
+ int get_obj_head_ioctx(const RGWBucketInfo& bucket_info, const rgw_obj& obj,
+ librados::IoCtx *ioctx);
+
// implements DoutPrefixProvider
std::ostream& gen_prefix(std::ostream& out) const { return out << "RGWRadosStore "; }
CephContext* get_cct() const override { return rados->ctx(); }
store = p_store;
}
-int seed::get_torrent_file(RGWRados::Object::Read &read_op,
+int seed::get_torrent_file(rgw::sal::RGWObject* object,
uint64_t &total_len,
ceph::bufferlist &bl_data,
rgw_obj &obj)
const set<string> obj_key{RGW_OBJ_TORRENT};
map<string, bufferlist> m;
- const int r = read_op.state.cur_ioctx->omap_get_vals_by_keys(oid, obj_key, &m);
+ const int r = object->omap_get_vals_by_keys(oid, obj_key, &m);
if (r < 0) {
ldout(s->cct, 0) << "ERROR: omap_get_vals_by_keys failed: " << r << dendl;
return r;
int get_params();
void init(struct req_state *p_req, rgw::sal::RGWRadosStore *p_store);
- int get_torrent_file(RGWRados::Object::Read &read_op,
+ int get_torrent_file(rgw::sal::RGWObject* object,
uint64_t &total_len,
ceph::bufferlist &bl_data,
rgw_obj &obj);