]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librgw: update mtime on write finish
authorMatt Benjamin <mbenjamin@redhat.com>
Thu, 17 Dec 2015 15:25:12 +0000 (10:25 -0500)
committerMatt Benjamin <mbenjamin@redhat.com>
Fri, 12 Feb 2016 17:06:51 +0000 (12:06 -0500)
Signed-off-by: Matt Benjamin <mbenjamin@redhat.com>
src/rgw/rgw_common.h
src/rgw/rgw_file.cc
src/rgw/rgw_file.h
src/rgw/rgw_op.cc
src/rgw/rgw_op.h
src/rgw/rgw_rest_swift.cc
src/rgw/rgw_swift.h

index 714b04dde7d1f5d7ad9d9bcf5fc08550c8cf5937..6c7ddd1d51e62f146f77fbbb54c8d60a1a465d16 100644 (file)
@@ -17,6 +17,7 @@
 #define CEPH_RGW_COMMON_H
 
 #include "common/ceph_crypto.h"
+
 #include "common/debug.h"
 #include "common/perf_counters.h"
 
index 430de4b00935e464cf3d1f5ce1afb9f27b6ba70f..137abb755fd4b7ff7514da0917018e4da9dc9235 100644 (file)
@@ -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<string, bufferlist> attrs;
+  map<string, string>::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 */
index d6f6fec050c36e2e787ee39507e682ac02880a85..c6b2e2d7feb045a0cb4dfc40293b06a3526774fd 100644 (file)
@@ -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;
   }
index 08eae5f0fb8adb8415e1b6ce6214faf6241e1ce0..4b6004b58f79d353aba568eea20c555cfabcb2f9 100644 (file)
@@ -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(<attr_name, attr_contents>, where attr_name is RGW_ATTR_PREFIX.HTTP_NAME)
- * s: The request state
- * attrs: will be filled up with attrs mapped as <attr_name, attr_contents>
- *
- */
-static void rgw_get_request_metadata(CephContext *cct,
-                                     struct req_info& info,
-                                     map<string, bufferlist>& attrs,
-                                     const bool allow_empty_attrs = true)
-{
-  map<string, string>::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<string, bufferlist>::value_type v(attr_name, bufferlist());
-      std::pair < map<string, bufferlist>::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<string, bufferlist>& 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<string, bufferlist>& 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;
index 388af73dbc1ac9bcf89981a35573ec00bb3b74d3..f2819e320c3fd620edecba3a84c0526af1a7b499 100644 (file)
 #include <set>
 #include <map>
 
+#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(<attr_name, attr_contents>, where attr_name is RGW_ATTR_PREFIX.HTTP_NAME)
+ * s: The request state
+ * attrs: will be filled up with attrs mapped as <attr_name, attr_contents>
+ *
+ */
+static inline void rgw_get_request_metadata(CephContext *cct,
+                                           struct req_info& info,
+                                           map<string, bufferlist>& attrs,
+                                           const bool allow_empty_attrs = true)
+{
+  map<string, string>::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<string, bufferlist>::value_type v(attr_name, bufferlist());
+      std::pair < map<string, bufferlist>::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<string, bufferlist>& 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<string, bufferlist>& 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 */
index 0f9fd2faf9d879c9e27242be0494d2ab5621b79e..dda1f173a8789174f2b7f5c5385b8f4130f908b3 100644 (file)
@@ -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"
index ff449e91b9e420e64d5f9e4a937ce3faf7ed719d..c87adee075c6ca7d428f689c4800747ac063ca7f 100644 (file)
@@ -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"