snprintf(buf, sizeof(buf), ".%lld", (long long)store->instance_id());
string client_id = store->zone_id() + buf;
string op_id = store->unique_id(store->get_new_req_id());
- map<string, bufferlist> attrs;
rgw_obj src_obj(bucket_info.bucket, key.name);
src_obj.set_instance(key.instance);
source_zone,
src_obj,
bucket_info, /* source */
- nullptr, /* real_time* src_mtime, */
+ pmtime, /* real_time* src_mtime, */
+ psize, /* uint64_t * */
nullptr, /* const real_time* mod_ptr, */
nullptr, /* const real_time* unmod_ptr, */
true, /* high precision time */
nullptr, /* const char *if_match, */
nullptr, /* const char *if_nomatch, */
- attrs,
+ pattrs,
nullptr,
nullptr, /* string *ptag, */
nullptr); /* string *petag, */
#define CEPH_RGW_CR_RADOS_H
#include "rgw_coroutine.h"
+#include "rgw_rados.h"
#include "common/WorkQueue.h"
#include "common/Throttle.h"
RGWBucketInfo bucket_info;
rgw_obj_key key;
- uint64_t versioned_epoch;
- real_time src_mtime;
+ ceph::real_time *pmtime;
+ uint64_t *psize;
+ map<string, bufferlist> *pattrs;
protected:
int _send_request();
const string& _source_zone,
RGWBucketInfo& _bucket_info,
const rgw_obj_key& _key,
- uint64_t _versioned_epoch) : RGWAsyncRadosRequest(caller, cn), store(_store),
+ ceph::real_time *_pmtime,
+ uint64_t *_psize,
+ map<string, bufferlist> *_pattrs) : RGWAsyncRadosRequest(caller, cn), store(_store),
source_zone(_source_zone),
bucket_info(_bucket_info),
key(_key),
- versioned_epoch(_versioned_epoch) {}
+ pmtime(_pmtime),
+ psize(_psize),
+ pattrs(_pattrs) {}
};
class RGWStatRemoteObjCR : public RGWSimpleCoroutine {
RGWBucketInfo bucket_info;
rgw_obj_key key;
- uint64_t versioned_epoch;
+
+ ceph::real_time *pmtime;
+ uint64_t *psize;
+ map<string, bufferlist> *pattrs;
RGWAsyncStatRemoteObj *req;
const string& _source_zone,
RGWBucketInfo& _bucket_info,
const rgw_obj_key& _key,
- uint64_t _versioned_epoch,
- bool _if_newer) : RGWSimpleCoroutine(_store->ctx()), cct(_store->ctx()),
+ ceph::real_time *_pmtime,
+ uint64_t *_psize,
+ map<string, bufferlist> *_pattrs) : RGWSimpleCoroutine(_store->ctx()), cct(_store->ctx()),
async_rados(_async_rados), store(_store),
source_zone(_source_zone),
bucket_info(_bucket_info),
key(_key),
- versioned_epoch(_versioned_epoch),
+ pmtime(_pmtime),
+ psize(_psize),
+ pattrs(_pattrs),
req(NULL) {}
}
int send_request() {
- req = new RGWAsyncStatRemoteObj(this, stack->create_completion_notifier(), store, source_zone, bucket_info,
- key, versioned_epoch);
+ req = new RGWAsyncStatRemoteObj(this, stack->create_completion_notifier(), store, source_zone,
+ bucket_info, key, pmtime, psize, pattrs);
async_rados->queue(req);
return 0;
}
utime_t gc_invalidate_time;
bool is_slo;
string lo_etag;
+ bool rgwx_stat; /* extended rgw stat operation */
int init_common();
public:
range_parsed = false;
skip_manifest = false;
is_slo = false;
+ rgwx_stat = false;
}
bool prefetch_data();
rgw_obj& src_obj,
RGWBucketInfo& src_bucket_info,
real_time *src_mtime,
+ uint64_t *psize,
const real_time *mod_ptr,
const real_time *unmod_ptr,
bool high_precision_time,
const char *if_match,
const char *if_nomatch,
- map<string, bufferlist>& attrs,
+ map<string, bufferlist> *pattrs,
string *version_id,
string *ptag,
string *petag)
int ret = conn->get_obj(user_id, info, src_obj, pmod, unmod_ptr,
dest_mtime_weight.zone_short_id, dest_mtime_weight.pg_ver,
- true, false, &cb, &in_stream_req);
+ true /* prepend_meta */, true /* GET */, true /* rgwx-stat */,
+ &cb, &in_stream_req);
if (ret < 0) {
return ret;
}
- ret = conn->complete_request(in_stream_req, etag, &set_mtime, req_headers);
+ ret = conn->complete_request(in_stream_req, etag, &set_mtime, psize, req_headers);
if (ret < 0) {
return ret;
}
}
}
- attrs = src_attrs;
+ if (pattrs) {
+ *pattrs = src_attrs;
+ }
return 0;
}
ret = conn->get_obj(user_id, info, src_obj, pmod, unmod_ptr,
dest_mtime_weight.zone_short_id, dest_mtime_weight.pg_ver,
- true, true, &cb, &in_stream_req);
+ true /* prepend_meta */, true /* GET */, false /* rgwx-stat */,
+ &cb, &in_stream_req);
if (ret < 0) {
goto set_err_state;
}
- ret = conn->complete_request(in_stream_req, etag, &set_mtime, req_headers);
+ ret = conn->complete_request(in_stream_req, etag, &set_mtime, nullptr, req_headers);
if (ret < 0) {
goto set_err_state;
}
rgw_obj& src_obj,
RGWBucketInfo& src_bucket_info,
real_time *src_mtime,
+ uint64_t *psize,
const real_time *mod_ptr,
const real_time *unmod_ptr,
bool high_precision_time,
const char *if_match,
const char *if_nomatch,
- map<string, bufferlist>& attrs,
+ map<string, bufferlist> *pattrs,
string *version_id,
string *ptag,
string *petag);
if (s->system_request) {
mod_zone_id = s->info.env->get_int("HTTP_DEST_ZONE_SHORT_ID", 0);
mod_pg_ver = s->info.env->get_int("HTTP_DEST_PG_VER", 0);
+ rgwx_stat = s->info.args.exists(RGW_SYS_PARAM_PREFIX "stat");
+ get_data &= (!rgwx_stat);
}
/* start gettorrent */
return 0;
}
-int RGWRESTStreamRWRequest::complete(string& etag, real_time *mtime, map<string, string>& attrs)
+int RGWRESTStreamRWRequest::complete(string& etag, real_time *mtime, uint64_t *psize, map<string, string>& attrs)
{
set_str_from_headers(out_headers, "ETAG", etag);
- if (status >= 0 && mtime) {
- string mtime_str;
- set_str_from_headers(out_headers, "RGWX_MTIME", mtime_str);
- if (!mtime_str.empty()) {
- int ret = parse_rgwx_mtime(cct, mtime_str, mtime);
- if (ret < 0) {
- return ret;
+ if (status >= 0) {
+ if (mtime) {
+ string mtime_str;
+ set_str_from_headers(out_headers, "RGWX_MTIME", mtime_str);
+ if (!mtime_str.empty()) {
+ int ret = parse_rgwx_mtime(cct, mtime_str, mtime);
+ if (ret < 0) {
+ return ret;
+ }
+ } else {
+ *mtime = real_time();
+ }
+ }
+ if (psize) {
+ string size_str;
+ set_str_from_headers(out_headers, "RGWX_OBJECT_SIZE", size_str);
+ string err;
+ *psize = strict_strtoll(size_str.c_str(), 10, &err);
+ if (!err.empty()) {
+ ldout(cct, 0) << "ERROR: failed parsing embedded metadata object size (" << size_str << ") to int " << dendl;
+ return -EIO;
}
- } else {
- *mtime = real_time();
}
}
virtual ~RGWRESTStreamRWRequest() {}
int get_obj(RGWAccessKey& key, map<string, string>& extra_headers, rgw_obj& obj);
int get_resource(RGWAccessKey& key, map<string, string>& extra_headers, const string& resource, RGWHTTPManager *mgr = NULL);
- int complete(string& etag, real_time *mtime, map<string, string>& attrs);
+ int complete(string& etag, real_time *mtime, uint64_t *psize, map<string, string>& attrs);
void set_outbl(bufferlist& _outbl) {
outbl.swap(_outbl);
int RGWRESTConn::get_obj(const rgw_user& uid, req_info *info /* optional */, rgw_obj& obj,
const real_time *mod_ptr, const real_time *unmod_ptr,
uint32_t mod_zone_id, uint64_t mod_pg_ver,
- bool prepend_metadata, bool read_data,
+ bool prepend_metadata, bool get_op, bool rgwx_stat,
RGWGetDataCB *cb, RGWRESTStreamRWRequest **req)
{
string url;
if (prepend_metadata) {
params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "prepend-metadata", self_zone_group));
}
+ if (rgwx_stat) {
+ params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "stat", "true"));
+ }
if (!obj.get_instance().empty()) {
const string& instance = obj.get_instance();
params.push_back(param_pair_t("versionId", instance));
}
- if (read_data) {
+ if (get_op) {
*req = new RGWRESTStreamReadRequest(cct, url, cb, NULL, ¶ms);
} else {
*req = new RGWRESTStreamHeadRequest(cct, url, cb, NULL, ¶ms);
return (*req)->get_obj(key, extra_headers, obj);
}
-int RGWRESTConn::complete_request(RGWRESTStreamRWRequest *req, string& etag, real_time *mtime, map<string, string>& attrs)
+int RGWRESTConn::complete_request(RGWRESTStreamRWRequest *req, string& etag, real_time *mtime,
+ uint64_t *psize, map<string, string>& attrs)
{
- int ret = req->complete(etag, mtime, attrs);
+ int ret = req->complete(etag, mtime, psize, attrs);
delete req;
return ret;
string etag;
map<string, string> attrs;
- return req.complete(etag, NULL, attrs);
+ return req.complete(etag, NULL, NULL, attrs);
}
RGWRESTReadResource::RGWRESTReadResource(RGWRESTConn *_conn,
string etag;
map<string, string> attrs;
- return req.complete(etag, NULL, attrs);
+ return req.complete(etag, NULL, NULL, attrs);
}
int RGWRESTReadResource::aio_read()
string etag;
map<string, string> attrs;
- return req.complete(etag, NULL, attrs);
+ return req.complete(etag, NULL, NULL, attrs);
}
int RGWRESTPostResource::aio_send(bufferlist& outbl)
int get_obj(const rgw_user& uid, req_info *info /* optional */, rgw_obj& obj,
const ceph::real_time *mod_ptr, const ceph::real_time *unmod_ptr,
uint32_t mod_zone_id, uint64_t mod_pg_ver,
- bool prepend_metadata, bool read_data,
+ bool prepend_metadata, bool get_op, bool rgwx_stat,
RGWGetDataCB *cb, RGWRESTStreamRWRequest **req);
- int complete_request(RGWRESTStreamRWRequest *req, string& etag, ceph::real_time *mtime, map<string, string>& attrs);
+ int complete_request(RGWRESTStreamRWRequest *req, string& etag, ceph::real_time *mtime, uint64_t *psize, map<string, string>& attrs);
int get_resource(const string& resource,
param_vec_t *extra_params,
if (s->system_request &&
s->info.args.exists(RGW_SYS_PARAM_PREFIX "prepend-metadata")) {
+ STREAM_IO(s)->print("Rgwx-Object-Size: %lld\r\n", (long long)total_len);
+
+ if (rgwx_stat) {
+ /*
+ * in this case, we're not returning the object's content, only the prepended
+ * extra metadata
+ */
+ total_len = 0;
+ }
+
/* JSON encode object metadata */
JSONFormatter jf;
jf.open_object_section("obj_metadata");