diff options
author | Yehuda Sadeh <yehuda@inktank.com> | 2013-06-11 18:51:14 -0700 |
---|---|---|
committer | Yehuda Sadeh <yehuda@inktank.com> | 2013-06-11 18:51:14 -0700 |
commit | 95434d16086af1d005aa4ac2d5c583c6787f987b (patch) | |
tree | 50c5ee4e76e89a11ce73425af2c13ed0d89161b1 | |
parent | 00743d50e09f48c71ce47f6b61907fa48a42f114 (diff) | |
download | ceph-95434d16086af1d005aa4ac2d5c583c6787f987b.tar.gz |
rgw: propagate mtime from remote rgw on copy
Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
-rw-r--r-- | src/rgw/rgw_op.cc | 27 | ||||
-rw-r--r-- | src/rgw/rgw_op.h | 6 | ||||
-rw-r--r-- | src/rgw/rgw_rados.cc | 6 | ||||
-rw-r--r-- | src/rgw/rgw_rados.h | 4 | ||||
-rw-r--r-- | src/rgw/rgw_rest.cc | 20 | ||||
-rw-r--r-- | src/rgw/rgw_rest.h | 1 | ||||
-rw-r--r-- | src/rgw/rgw_rest_client.cc | 49 | ||||
-rw-r--r-- | src/rgw/rgw_rest_client.h | 10 | ||||
-rw-r--r-- | src/rgw/rgw_rest_conn.cc | 8 | ||||
-rw-r--r-- | src/rgw/rgw_rest_conn.h | 4 | ||||
-rw-r--r-- | src/rgw/rgw_rest_s3.cc | 3 |
11 files changed, 97 insertions, 41 deletions
diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 86618bd674b..c30987b8e22 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -1022,9 +1022,9 @@ int RGWPutObj::verify_permission() return 0; } -int RGWPutObjProcessor::complete(string& etag, map<string, bufferlist>& attrs) +int RGWPutObjProcessor::complete(string& etag, time_t *mtime, map<string, bufferlist>& attrs) { - int r = do_complete(etag, attrs); + int r = do_complete(etag, mtime, attrs); if (r < 0) return r; @@ -1060,7 +1060,7 @@ protected: int prepare(RGWRados *store, struct req_state *s); int handle_data(bufferlist& bl, off_t ofs, void **phandle); int throttle_data(void *handle) { return 0; } - int do_complete(string& etag, map<string, bufferlist>& attrs); + int do_complete(string& etag, time_t *mtime, map<string, bufferlist>& attrs); public: RGWPutObjProcessor_Plain() : ofs(0) {} @@ -1086,9 +1086,9 @@ int RGWPutObjProcessor_Plain::handle_data(bufferlist& bl, off_t _ofs, void **pha return 0; } -int RGWPutObjProcessor_Plain::do_complete(string& etag, map<string, bufferlist>& attrs) +int RGWPutObjProcessor_Plain::do_complete(string& etag, time_t *mtime, map<string, bufferlist>& attrs) { - int r = store->put_obj_meta(s->obj_ctx, obj, data.length(), attrs, + int r = store->put_obj_meta(s->obj_ctx, obj, data.length(), mtime, attrs, RGW_OBJ_CATEGORY_MAIN, PUT_OBJ_CREATE, &data); return r; @@ -1210,7 +1210,7 @@ protected: virtual bool immutable_head() { return false; } int prepare(RGWRados *store, struct req_state *s); - virtual int do_complete(string& etag, map<string, bufferlist>& attrs); + virtual int do_complete(string& etag, time_t *mtime, map<string, bufferlist>& attrs); void prepare_next_part(off_t ofs); void complete_parts(); @@ -1291,7 +1291,7 @@ void RGWPutObjProcessor_Atomic::complete_parts() prepare_next_part(obj_len); } -int RGWPutObjProcessor_Atomic::do_complete(string& etag, map<string, bufferlist>& attrs) +int RGWPutObjProcessor_Atomic::do_complete(string& etag, time_t *mtime, map<string, bufferlist>& attrs) { complete_parts(); @@ -1302,6 +1302,7 @@ int RGWPutObjProcessor_Atomic::do_complete(string& etag, map<string, bufferlist> extra_params.data = &first_chunk; extra_params.manifest = &manifest; extra_params.ptag = &s->req_id; /* use req_id as operation tag */ + extra_params.mtime = mtime; int r = store->put_obj_meta(s->obj_ctx, head_obj, obj_len, attrs, RGW_OBJ_CATEGORY_MAIN, PUT_OBJ_CREATE, @@ -1317,7 +1318,7 @@ class RGWPutObjProcessor_Multipart : public RGWPutObjProcessor_Atomic protected: bool immutable_head() { return true; } int prepare(RGWRados *store, struct req_state *s); - int do_complete(string& etag, map<string, bufferlist>& attrs); + int do_complete(string& etag, time_t *mtime, map<string, bufferlist>& attrs); public: RGWPutObjProcessor_Multipart(uint64_t _p) : RGWPutObjProcessor_Atomic(_p) {} @@ -1347,11 +1348,11 @@ int RGWPutObjProcessor_Multipart::prepare(RGWRados *store, struct req_state *s) return 0; } -int RGWPutObjProcessor_Multipart::do_complete(string& etag, map<string, bufferlist>& attrs) +int RGWPutObjProcessor_Multipart::do_complete(string& etag, time_t *mtime, map<string, bufferlist>& attrs) { complete_parts(); - int r = store->put_obj_meta(s->obj_ctx, head_obj, s->obj_size, attrs, RGW_OBJ_CATEGORY_MAIN, 0); + int r = store->put_obj_meta(s->obj_ctx, head_obj, s->obj_size, mtime, attrs, RGW_OBJ_CATEGORY_MAIN, 0); if (r < 0) return r; @@ -1514,7 +1515,7 @@ void RGWPutObj::execute() rgw_get_request_metadata(s->cct, s->info, attrs); - ret = processor->complete(etag, attrs); + ret = processor->complete(etag, &mtime, attrs); done: dispose_processor(processor); perfcounter->tinc(l_rgw_put_lat, @@ -1630,7 +1631,7 @@ void RGWPostObj::execute() attrs[RGW_ATTR_CONTENT_TYPE] = ct_bl; } - ret = processor->complete(etag, attrs); + ret = processor->complete(etag, NULL, attrs); done: dispose_processor(processor); @@ -2233,7 +2234,7 @@ void RGWInitMultipart::execute() obj.init_ns(s->bucket, tmp_obj_name, mp_ns); // the meta object will be indexed with 0 size, we c - ret = store->put_obj_meta(s->obj_ctx, obj, 0, attrs, RGW_OBJ_CATEGORY_MULTIMETA, PUT_OBJ_CREATE_EXCL); + ret = store->put_obj_meta(s->obj_ctx, obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MULTIMETA, PUT_OBJ_CREATE_EXCL); } while (ret == -EEXIST); } diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index 55011b4102f..09238778cff 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -274,7 +274,7 @@ protected: struct req_state *s; bool is_complete; - virtual int do_complete(string& etag, map<string, bufferlist>& attrs) = 0; + virtual int do_complete(string& etag, time_t *mtime, map<string, bufferlist>& attrs) = 0; list<rgw_obj> objs; @@ -291,7 +291,7 @@ public: }; virtual int handle_data(bufferlist& bl, off_t ofs, void **phandle) = 0; virtual int throttle_data(void *handle) = 0; - virtual int complete(string& etag, map<string, bufferlist>& attrs); + virtual int complete(string& etag, time_t *mtime, map<string, bufferlist>& attrs); }; class RGWPutObj : public RGWOp { @@ -307,6 +307,7 @@ protected: bool chunked_upload; RGWAccessControlPolicy policy; const char *obj_manifest; + time_t mtime; public: RGWPutObj() { @@ -316,6 +317,7 @@ public: supplied_etag = NULL; chunked_upload = false; obj_manifest = NULL; + mtime = 0; } virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) { diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index d115fc731a4..05d9ceffc01 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -1975,7 +1975,7 @@ int RGWRados::copy_obj(void *ctx, map<string, bufferlist> src_attrs; - RGWRESTStreamRequest *out_stream_req; + RGWRESTStreamWriteRequest *out_stream_req; int ret = rest_conn->put_obj_init(user_id, dest_obj, astate->size, attrset, &out_stream_req); if (ret < 0) @@ -1985,7 +1985,9 @@ int RGWRados::copy_obj(void *ctx, if (ret < 0) return ret; - ret = rest_conn->complete_request(out_stream_req); + string etag; + + ret = rest_conn->complete_request(out_stream_req, etag, mtime); if (ret < 0) return ret; diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index cee93e913c0..771cde77e95 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -679,10 +679,10 @@ public: RGWObjManifest *manifest, const string *ptag, list<string> *remove_objs, bool modify_version, RGWObjVersionTracker *objv_tracker); - virtual int put_obj_meta(void *ctx, rgw_obj& obj, uint64_t size, + virtual int put_obj_meta(void *ctx, rgw_obj& obj, uint64_t size, time_t *mtime, map<std::string, bufferlist>& attrs, RGWObjCategory category, int flags, const bufferlist *data = NULL) { - return put_obj_meta_impl(ctx, obj, size, NULL, attrs, category, flags, + return put_obj_meta_impl(ctx, obj, size, mtime, attrs, category, flags, NULL, data, NULL, NULL, NULL, false, NULL); } diff --git a/src/rgw/rgw_rest.cc b/src/rgw/rgw_rest.cc index 76461433774..d2c277446fd 100644 --- a/src/rgw/rgw_rest.cc +++ b/src/rgw/rgw_rest.cc @@ -302,7 +302,7 @@ void dump_redirect(struct req_state *s, const string& redirect) s->cio->print("Location: %s\n", redirect.c_str()); } -void dump_last_modified(struct req_state *s, time_t t) +static void dump_time_header(struct req_state *s, const char *name, time_t t) { char timestr[TIME_BUF_SIZE]; @@ -314,7 +314,23 @@ void dump_last_modified(struct req_state *s, time_t t) if (strftime(timestr, sizeof(timestr), "%a, %d %b %Y %H:%M:%S %Z", tmp) == 0) return; - int r = s->cio->print("Last-Modified: %s\n", timestr); + int r = s->cio->print("%s: %s\n", name, timestr); + if (r < 0) { + ldout(s->cct, 0) << "ERROR: s->cio->print() returned err=" << r << dendl; + } +} + +void dump_last_modified(struct req_state *s, time_t t) +{ + dump_time_header(s, "Last-Modified", t); +} + +void dump_epoch_header(struct req_state *s, const char *name, time_t t) +{ + char buf[32]; + snprintf(buf, sizeof(buf), "%lld", (long long)t); + + int r = s->cio->print("%s: %s\n", name, buf); if (r < 0) { ldout(s->cct, 0) << "ERROR: s->cio->print() returned err=" << r << dendl; } diff --git a/src/rgw/rgw_rest.h b/src/rgw/rgw_rest.h index e3b20bd7160..0b7204fe9cb 100644 --- a/src/rgw/rgw_rest.h +++ b/src/rgw/rgw_rest.h @@ -314,6 +314,7 @@ extern void list_all_buckets_start(struct req_state *s); extern void dump_owner(struct req_state *s, string& id, string& name, const char *section = NULL); extern void dump_content_length(struct req_state *s, uint64_t len); extern void dump_etag(struct req_state *s, const char *etag); +extern void dump_epoch_header(struct req_state *s, const char *name, time_t t); extern void dump_last_modified(struct req_state *s, time_t t); extern void abort_early(struct req_state *s, int err); extern void dump_range(struct req_state *s, uint64_t ofs, uint64_t end, uint64_t total_size); diff --git a/src/rgw/rgw_rest_client.cc b/src/rgw/rgw_rest_client.cc index 7a78bb8f9cd..aa01b499f2c 100644 --- a/src/rgw/rgw_rest_client.cc +++ b/src/rgw/rgw_rest_client.cc @@ -6,6 +6,7 @@ #include "common/ceph_crypto_cms.h" #include "common/armor.h" +#include "common/strtol.h" #define dout_subsys ceph_subsys_rgw @@ -43,7 +44,13 @@ int RGWRESTSimpleRequest::receive_header(void *ptr, size_t len) char buf[len + 1]; size_t i; for (i = 0; i < len && *src; ++i, ++src) { - buf[i] = toupper(*src); + switch (*src) { + case '-': + buf[i] = '_'; + break; + default: + buf[i] = toupper(*src); + } } buf[i] = '\0'; out_headers[buf] = l; @@ -252,9 +259,9 @@ int RGWRESTSimpleRequest::forward_request(RGWAccessKey& key, req_info& info, siz } class RGWRESTStreamOutCB : public RGWGetDataCB { - RGWRESTStreamRequest *req; + RGWRESTStreamWriteRequest *req; public: - RGWRESTStreamOutCB(RGWRESTStreamRequest *_req) : req(_req) {} + RGWRESTStreamOutCB(RGWRESTStreamWriteRequest *_req) : req(_req) {} int handle_data(bufferlist& bl, off_t bl_ofs, off_t bl_len); /* callback for object iteration when sending data */ }; @@ -272,12 +279,12 @@ int RGWRESTStreamOutCB::handle_data(bufferlist& bl, off_t bl_ofs, off_t bl_len) return req->add_output_data(new_bl); } -RGWRESTStreamRequest::~RGWRESTStreamRequest() +RGWRESTStreamWriteRequest::~RGWRESTStreamWriteRequest() { delete cb; } -int RGWRESTStreamRequest::add_output_data(bufferlist& bl) +int RGWRESTStreamWriteRequest::add_output_data(bufferlist& bl) { lock.Lock(); if (status < 0) { @@ -362,7 +369,7 @@ static void add_grants_headers(map<int, string>& grants, map<string, string>& at } } -int RGWRESTStreamRequest::put_obj_init(RGWAccessKey& key, rgw_obj& obj, uint64_t obj_size, map<string, bufferlist>& attrs) +int RGWRESTStreamWriteRequest::put_obj_init(RGWAccessKey& key, rgw_obj& obj, uint64_t obj_size, map<string, bufferlist>& attrs) { string resource = obj.bucket.name + "/" + obj.object; string new_url = url; @@ -444,11 +451,11 @@ int RGWRESTStreamRequest::put_obj_init(RGWAccessKey& key, rgw_obj& obj, uint64_t return 0; } -int RGWRESTStreamRequest::send_data(void *ptr, size_t len) +int RGWRESTStreamWriteRequest::send_data(void *ptr, size_t len) { uint64_t sent = 0; - dout(20) << "RGWRESTStreamRequest::send_data()" << dendl; + dout(20) << "RGWRESTStreamWriteRequest::send_data()" << dendl; lock.Lock(); if (pending_send.empty() || status < 0) { lock.Unlock(); @@ -489,11 +496,35 @@ int RGWRESTStreamRequest::send_data(void *ptr, size_t len) } -int RGWRESTStreamRequest::complete() +void set_str_from_headers(map<string, string>& out_headers, const string& header_name, string& str) +{ + map<string, string>::iterator iter = out_headers.find(header_name); + if (iter != out_headers.end()) { + str = iter->second; + } else { + str.clear(); + } +} + + +int RGWRESTStreamWriteRequest::complete(string& etag, time_t *mtime) { int ret = complete_request(handle); if (ret < 0) return ret; + set_str_from_headers(out_headers, "ETAG", etag); + if (mtime) { + string mtime_str; + set_str_from_headers(out_headers, "RGWX_MTIME", mtime_str); + string err; + long t = strict_strtol(mtime_str.c_str(), 10, &err); + if (!err.empty()) { + ldout(cct, 0) << "ERROR: failed converting mtime (" << mtime_str << ") to int " << dendl; + return -EINVAL; + } + *mtime = (time_t)t; + } + return status; } diff --git a/src/rgw/rgw_rest_client.h b/src/rgw/rgw_rest_client.h index cb744f4f695..a7cc571819f 100644 --- a/src/rgw/rgw_rest_client.h +++ b/src/rgw/rgw_rest_client.h @@ -53,7 +53,7 @@ public: }; -class RGWRESTStreamRequest : public RGWRESTSimpleRequest { +class RGWRESTStreamWriteRequest : public RGWRESTSimpleRequest { Mutex lock; list<bufferlist> pending_send; void *handle; @@ -62,12 +62,12 @@ public: int add_output_data(bufferlist& bl); int send_data(void *ptr, size_t len); - RGWRESTStreamRequest(CephContext *_cct, string& _url, list<pair<string, string> > *_headers, + RGWRESTStreamWriteRequest(CephContext *_cct, string& _url, list<pair<string, string> > *_headers, list<pair<string, string> > *_params) : RGWRESTSimpleRequest(_cct, _url, _headers, _params), - lock("RGWRESTStreamRequest"), handle(NULL), cb(NULL) {} - ~RGWRESTStreamRequest(); + lock("RGWRESTStreamWriteRequest"), handle(NULL), cb(NULL) {} + ~RGWRESTStreamWriteRequest(); int put_obj_init(RGWAccessKey& key, rgw_obj& obj, uint64_t obj_size, map<string, bufferlist>& attrs); - int complete(); + int complete(string& etag, time_t *mtime); RGWGetDataCB *get_out_cb() { return cb; } }; diff --git a/src/rgw/rgw_rest_conn.cc b/src/rgw/rgw_rest_conn.cc index 8dc2c502d53..71f97d861f5 100644 --- a/src/rgw/rgw_rest_conn.cc +++ b/src/rgw/rgw_rest_conn.cc @@ -47,7 +47,7 @@ public: }; int RGWRegionConnection::put_obj_init(const string& uid, rgw_obj& obj, uint64_t obj_size, - map<string, bufferlist>& attrs, RGWRESTStreamRequest **req) + map<string, bufferlist>& attrs, RGWRESTStreamWriteRequest **req) { string url; int ret = get_url(url); @@ -57,13 +57,13 @@ int RGWRegionConnection::put_obj_init(const string& uid, rgw_obj& obj, uint64_t list<pair<string, string> > params; params.push_back(make_pair<string, string>(RGW_SYS_PARAM_PREFIX "uid", uid)); params.push_back(make_pair<string, string>(RGW_SYS_PARAM_PREFIX "region", region)); - *req = new RGWRESTStreamRequest(cct, url, NULL, ¶ms); + *req = new RGWRESTStreamWriteRequest(cct, url, NULL, ¶ms); return (*req)->put_obj_init(key, obj, obj_size, attrs); } -int RGWRegionConnection::complete_request(RGWRESTStreamRequest *req) +int RGWRegionConnection::complete_request(RGWRESTStreamWriteRequest *req, string& etag, time_t *mtime) { - int ret = req->complete(); + int ret = req->complete(etag, mtime); delete req; return ret; diff --git a/src/rgw/rgw_rest_conn.h b/src/rgw/rgw_rest_conn.h index 5119cdc250e..f9e35e4dedf 100644 --- a/src/rgw/rgw_rest_conn.h +++ b/src/rgw/rgw_rest_conn.h @@ -25,8 +25,8 @@ public: /* async request */ int put_obj_init(const string& uid, rgw_obj& obj, uint64_t obj_size, - map<string, bufferlist>& attrs, RGWRESTStreamRequest **req); - int complete_request(RGWRESTStreamRequest *req); + map<string, bufferlist>& attrs, RGWRESTStreamWriteRequest **req); + int complete_request(RGWRESTStreamWriteRequest *req, string& etag, time_t *mtime); }; #endif diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 831959f2547..4aaf1cd3bae 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -480,6 +480,9 @@ void RGWPutObj_ObjStore_S3::send_response() dump_etag(s, etag.c_str()); dump_content_length(s, 0); } + if (s->system_request && mtime) { + dump_epoch_header(s, "Rgwx-Mtime", mtime); + } dump_errno(s); end_header(s); } |