From: Matt Benjamin Date: Thu, 17 Dec 2015 15:25:12 +0000 (-0500) Subject: librgw: update mtime on write finish X-Git-Tag: v10.1.0~382^2~98 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=5d9e395cb036faabcd7bf93dc842973de683ccbc;p=ceph.git librgw: update mtime on write finish Signed-off-by: Matt Benjamin --- diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index 714b04dde7d1..6c7ddd1d51e6 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -17,6 +17,7 @@ #define CEPH_RGW_COMMON_H #include "common/ceph_crypto.h" + #include "common/debug.h" #include "common/perf_counters.h" diff --git a/src/rgw/rgw_file.cc b/src/rgw/rgw_file.cc index 430de4b00935..137abb755fd4 100644 --- a/src/rgw/rgw_file.cc +++ b/src/rgw/rgw_file.cc @@ -119,8 +119,8 @@ int RGWFileHandle::write(uint64_t off, size_t len, size_t *bytes_written, /* start */ std::string object_name = full_object_name(); f->write_req = - new RGWWriteRequest(fs->get_context(), fs->get_user(), bucket_name(), - object_name); + new RGWWriteRequest(fs->get_context(), fs->get_user(), this, + bucket_name(), object_name); rc = librgw.get_fe()->start_req(f->write_req); } @@ -264,7 +264,98 @@ done: int RGWWriteRequest::exec_finish() { - return 0; + bufferlist bl, aclbl; + map attrs; + map::iterator iter; + char calc_md5[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1]; + unsigned char m[CEPH_CRYPTO_MD5_DIGESTSIZE]; + struct req_state* s = get_state(); + + s->obj_size = ofs; // XXX check ofs + perfcounter->inc(l_rgw_put_b, s->obj_size); + + op_ret = get_store()->check_quota(s->bucket_owner.get_id(), s->bucket, + user_quota, bucket_quota, s->obj_size); + if (op_ret < 0) { + goto done; + } + + if (need_calc_md5) { + processor->complete_hash(&hash); + } + hash.Final(m); + + buf_to_hex(m, CEPH_CRYPTO_MD5_DIGESTSIZE, calc_md5); + etag = calc_md5; + +#if 0 /* XXX only in PostObj currently */ + if (supplied_md5_b64 && strcmp(calc_md5, supplied_md5)) { + op_ret = -ERR_BAD_DIGEST; + goto done; + } +#endif + + policy.encode(aclbl); + + attrs[RGW_ATTR_ACL] = aclbl; + + /* XXX most of the following cases won't currently arise */ + if (unlikely(!! dlo_manifest)) { + op_ret = encode_dlo_manifest_attr(dlo_manifest, attrs); + if (op_ret < 0) { + ldout(s->cct, 0) << "bad user manifest: " << dlo_manifest << dendl; + goto done; + } + complete_etag(hash, &etag); + ldout(s->cct, 10) << __func__ << ": calculated md5 for user manifest: " + << etag << dendl; + } + + if (unlikely(!! slo_info)) { + bufferlist manifest_bl; + ::encode(*slo_info, manifest_bl); + attrs[RGW_ATTR_SLO_MANIFEST] = manifest_bl; + + hash.Update((byte *)slo_info->raw_data, slo_info->raw_data_len); + complete_etag(hash, &etag); + ldout(s->cct, 10) << __func__ << ": calculated md5 for user manifest: " + << etag << dendl; + } + + if (supplied_etag && etag.compare(supplied_etag) != 0) { + op_ret = -ERR_UNPROCESSABLE_ENTITY; + goto done; + } + bl.append(etag.c_str(), etag.size() + 1); + attrs[RGW_ATTR_ETAG] = bl; + + for (iter = s->generic_attrs.begin(); iter != s->generic_attrs.end(); + ++iter) { + bufferlist& attrbl = attrs[iter->first]; + const string& val = iter->second; + attrbl.append(val.c_str(), val.size() + 1); + } + + rgw_get_request_metadata(s->cct, s->info, attrs); + encode_delete_at_attr(delete_at, attrs); + + /* Add a custom metadata to expose the information whether an object + * is an SLO or not. Appending the attribute must be performed AFTER + * processing any input from user in order to prohibit overwriting. */ + if (unlikely(!! slo_info)) { + bufferlist slo_userindicator_bl; + ::encode("True", slo_userindicator_bl); + attrs[RGW_ATTR_SLO_UINDICATOR] = slo_userindicator_bl; + } + + op_ret = processor->complete(etag, &mtime, 0, attrs, delete_at, if_match, + if_nomatch); + +done: + dispose_processor(processor); + perfcounter->tinc(l_rgw_put_lat, + (ceph_clock_now(s->cct) - s->time)); + return op_ret; } /* exec_finish */ /* librgw */ diff --git a/src/rgw/rgw_file.h b/src/rgw/rgw_file.h index d6f6fec050c3..c6b2e2d7feb0 100644 --- a/src/rgw/rgw_file.h +++ b/src/rgw/rgw_file.h @@ -1457,6 +1457,7 @@ class RGWWriteRequest : public RGWLibContinuedReq, public: const std::string& bucket_name; const std::string& obj_name; + RGWFileHandle* rgw_fh; RGWPutObjProcessor *processor; buffer::list data; MD5 hash; @@ -1466,11 +1467,11 @@ public: bool multipart; bool need_calc_md5; - RGWWriteRequest(CephContext* _cct, RGWUserInfo *_user, + RGWWriteRequest(CephContext* _cct, RGWUserInfo *_user, RGWFileHandle* _fh, const std::string& _bname, const std::string& _oname) : RGWLibContinuedReq(_cct, _user), bucket_name(_bname), obj_name(_oname), - processor(nullptr), last_off(0), next_off(0), bytes_written(0), - multipart(false) { + rgw_fh(_fh), processor(nullptr), last_off(0), next_off(0), + bytes_written(0), multipart(false) { magic = 81; op = this; } diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 08eae5f0fb8a..4b6004b58f79 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -119,57 +119,6 @@ done: return r; } -static void format_xattr(std::string &xattr) -{ - /* If the extended attribute is not valid UTF-8, we encode it using quoted-printable - * encoding. - */ - if ((check_utf8(xattr.c_str(), xattr.length()) != 0) || - (check_for_control_characters(xattr.c_str(), xattr.length()) != 0)) { - static const char MIME_PREFIX_STR[] = "=?UTF-8?Q?"; - static const int MIME_PREFIX_LEN = sizeof(MIME_PREFIX_STR) - 1; - static const char MIME_SUFFIX_STR[] = "?="; - static const int MIME_SUFFIX_LEN = sizeof(MIME_SUFFIX_STR) - 1; - int mlen = mime_encode_as_qp(xattr.c_str(), NULL, 0); - char *mime = new char[MIME_PREFIX_LEN + mlen + MIME_SUFFIX_LEN + 1]; - strcpy(mime, MIME_PREFIX_STR); - mime_encode_as_qp(xattr.c_str(), mime + MIME_PREFIX_LEN, mlen); - strcpy(mime + MIME_PREFIX_LEN + (mlen - 1), MIME_SUFFIX_STR); - xattr.assign(mime); - delete [] mime; - } -} - -/** - * Get the HTTP request metadata out of the req_state as a - * map(, where attr_name is RGW_ATTR_PREFIX.HTTP_NAME) - * s: The request state - * attrs: will be filled up with attrs mapped as - * - */ -static void rgw_get_request_metadata(CephContext *cct, - struct req_info& info, - map& attrs, - const bool allow_empty_attrs = true) -{ - map::iterator iter; - for (iter = info.x_meta_map.begin(); iter != info.x_meta_map.end(); ++iter) { - const string &name(iter->first); - string &xattr(iter->second); - - if (allow_empty_attrs || !xattr.empty()) { - ldout(cct, 10) << "x>> " << name << ":" << xattr << dendl; - format_xattr(xattr); - string attr_name(RGW_ATTR_PREFIX); - attr_name.append(name); - map::value_type v(attr_name, bufferlist()); - std::pair < map::iterator, bool > rval(attrs.insert(v)); - bufferlist& bl(rval.first->second); - bl.append(xattr.c_str(), xattr.size() + 1); - } - } -} - static int decode_policy(CephContext *cct, bufferlist& bl, RGWAccessControlPolicy *policy) { bufferlist::iterator iter = bl.begin(); @@ -2112,44 +2061,6 @@ void RGWPutObj::pre_exec() rgw_bucket_object_pre_exec(s); } -static void encode_delete_at_attr(time_t delete_at, map& attrs) -{ - if (delete_at == 0) { - return; - } - - bufferlist delatbl; - ::encode(utime_t(delete_at, 0), delatbl); - attrs[RGW_ATTR_DELETE_AT] = delatbl; -} - -static int encode_dlo_manifest_attr(const char * const dlo_manifest, - map& attrs) -{ - string dm = dlo_manifest; - - if (dm.find('/') == string::npos) { - return -EINVAL; - } - - bufferlist manifest_bl; - manifest_bl.append(dlo_manifest, strlen(dlo_manifest) + 1); - attrs[RGW_ATTR_USER_MANIFEST] = manifest_bl; - - return 0; -} - -static void complete_etag(MD5& hash, string *etag) -{ - char etag_buf[CEPH_CRYPTO_MD5_DIGESTSIZE]; - char etag_buf_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 16]; - - hash.Final((byte *)etag_buf); - buf_to_hex((const unsigned char *)etag_buf, CEPH_CRYPTO_MD5_DIGESTSIZE, etag_buf_str); - - *etag = etag_buf_str; -} - void RGWPutObj::execute() { RGWPutObjProcessor *processor = NULL; diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index 388af73dbc1a..f2819e320c3f 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -18,6 +18,12 @@ #include #include +#include "common/armor.h" +#include "common/mime.h" +#include "common/utf8.h" +#include "common/ceph_json.h" +#include "common/utf8.h" + #include "rgw_common.h" #include "rgw_rados.h" #include "rgw_user.h" @@ -26,6 +32,8 @@ #include "rgw_cors.h" #include "rgw_quota.h" +#include "include/assert.h" + using namespace std; struct req_state; @@ -1383,4 +1391,96 @@ static inline int get_system_versioning_params(req_state *s, return 0; } /* get_system_versioning_params */ +static inline void format_xattr(std::string &xattr) +{ + /* If the extended attribute is not valid UTF-8, we encode it using + * quoted-printable encoding. + */ + if ((check_utf8(xattr.c_str(), xattr.length()) != 0) || + (check_for_control_characters(xattr.c_str(), xattr.length()) != 0)) { + static const char MIME_PREFIX_STR[] = "=?UTF-8?Q?"; + static const int MIME_PREFIX_LEN = sizeof(MIME_PREFIX_STR) - 1; + static const char MIME_SUFFIX_STR[] = "?="; + static const int MIME_SUFFIX_LEN = sizeof(MIME_SUFFIX_STR) - 1; + int mlen = mime_encode_as_qp(xattr.c_str(), NULL, 0); + char *mime = new char[MIME_PREFIX_LEN + mlen + MIME_SUFFIX_LEN + 1]; + strcpy(mime, MIME_PREFIX_STR); + mime_encode_as_qp(xattr.c_str(), mime + MIME_PREFIX_LEN, mlen); + strcpy(mime + MIME_PREFIX_LEN + (mlen - 1), MIME_SUFFIX_STR); + xattr.assign(mime); + delete [] mime; + } +} /* format_xattr */ + +/** + * Get the HTTP request metadata out of the req_state as a + * map(, where attr_name is RGW_ATTR_PREFIX.HTTP_NAME) + * s: The request state + * attrs: will be filled up with attrs mapped as + * + */ +static inline void rgw_get_request_metadata(CephContext *cct, + struct req_info& info, + map& attrs, + const bool allow_empty_attrs = true) +{ + map::iterator iter; + for (iter = info.x_meta_map.begin(); iter != info.x_meta_map.end(); ++iter) { + const string &name(iter->first); + string &xattr(iter->second); + + if (allow_empty_attrs || !xattr.empty()) { + lsubdout(cct, rgw, 10) << "x>> " << name << ":" << xattr << dendl; + format_xattr(xattr); + string attr_name(RGW_ATTR_PREFIX); + attr_name.append(name); + map::value_type v(attr_name, bufferlist()); + std::pair < map::iterator, bool > + rval(attrs.insert(v)); + bufferlist& bl(rval.first->second); + bl.append(xattr.c_str(), xattr.size() + 1); + } + } +} /* rgw_get_request_metadata */ + +static inline void encode_delete_at_attr(time_t delete_at, + map& attrs) +{ + if (delete_at == 0) { + return; + } + + bufferlist delatbl; + ::encode(utime_t(delete_at, 0), delatbl); + attrs[RGW_ATTR_DELETE_AT] = delatbl; +} /* encode_delete_at_attr */ + +static inline int encode_dlo_manifest_attr(const char * const dlo_manifest, + map& attrs) +{ + string dm = dlo_manifest; + + if (dm.find('/') == string::npos) { + return -EINVAL; + } + + bufferlist manifest_bl; + manifest_bl.append(dlo_manifest, strlen(dlo_manifest) + 1); + attrs[RGW_ATTR_USER_MANIFEST] = manifest_bl; + + return 0; +} /* encode_dlo_manifest_attr */ + +static inline void complete_etag(MD5& hash, string *etag) +{ + char etag_buf[CEPH_CRYPTO_MD5_DIGESTSIZE]; + char etag_buf_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 16]; + + hash.Final((byte *)etag_buf); + buf_to_hex((const unsigned char *)etag_buf, CEPH_CRYPTO_MD5_DIGESTSIZE, + etag_buf_str); + + *etag = etag_buf_str; +} /* complete_etag */ + #endif /* CEPH_RGW_OP_H */ diff --git a/src/rgw/rgw_rest_swift.cc b/src/rgw/rgw_rest_swift.cc index 0f9fd2faf9d8..dda1f173a878 100644 --- a/src/rgw/rgw_rest_swift.cc +++ b/src/rgw/rgw_rest_swift.cc @@ -1,8 +1,12 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab +#include "include/assert.h" + #include "common/Formatter.h" #include "common/utf8.h" +#include "common/ceph_json.h" + #include "rgw_swift.h" #include "rgw_rest_swift.h" #include "rgw_acl_swift.h" diff --git a/src/rgw/rgw_swift.h b/src/rgw/rgw_swift.h index ff449e91b9e4..c87adee075c6 100644 --- a/src/rgw/rgw_swift.h +++ b/src/rgw/rgw_swift.h @@ -5,6 +5,8 @@ #ifndef CEPH_RGW_SWIFT_H #define CEPH_RGW_SWIFT_H +#include "include/assert.h" + #include "rgw_common.h" #include "common/Cond.h"