#define RGW_ATTR_SHADOW_OBJ RGW_ATTR_PREFIX "shadow_name"
#define RGW_ATTR_MANIFEST RGW_ATTR_PREFIX "manifest"
#define RGW_ATTR_USER_MANIFEST RGW_ATTR_PREFIX "user_manifest"
+#define RGW_ATTR_SLO_MANIFEST RGW_ATTR_PREFIX "slo_manifest"
#define RGW_ATTR_TEMPURL_KEY1 RGW_ATTR_META_PREFIX "temp-url-key"
#define RGW_ATTR_TEMPURL_KEY2 RGW_ATTR_META_PREFIX "temp-url-key-2"
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;
map<string, string>::iterator iter;
bool multipart;
- bool need_calc_md5 = (dlo_manifest == NULL);
+ bool need_calc_md5 = (dlo_manifest == NULL) && (slo_info == NULL);
perfcounter->inc(l_rgw_put);
goto done;
}
s->obj_size = ofs;
+
perfcounter->inc(l_rgw_put_b, s->obj_size);
ret = store->check_quota(s->bucket_owner.get_id(), s->bucket,
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 (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) {
string etag;
uint64_t size_bytes;
+ rgw_slo_entry() : size_bytes(0) {}
+
+ void encode(bufferlist& bl) const {
+ ENCODE_START(1, 1, bl);
+ ::encode(path, bl);
+ ::encode(etag, bl);
+ ::encode(size_bytes, bl);
+ ENCODE_FINISH(bl);
+ }
+
+ void decode(bufferlist::iterator& bl) {
+ DECODE_START(1, bl);
+ ::decode(path, bl);
+ ::decode(etag, bl);
+ ::decode(size_bytes, bl);
+ DECODE_FINISH(bl);
+ }
+
void decode_json(JSONObj *obj);
};
+WRITE_CLASS_ENCODER(rgw_slo_entry)
struct RGWSLOInfo {
vector<rgw_slo_entry> entries;
+ char *raw_data; /* in memory only */
+ int raw_data_len;
+
+ RGWSLOInfo() : raw_data(NULL), raw_data_len(0) {}
+ ~RGWSLOInfo() {
+ free(raw_data);
+ }
+
+ void encode(bufferlist& bl) const {
+ ENCODE_START(1, 1, bl);
+ ::encode(entries, bl);
+ ENCODE_FINISH(bl);
+ }
+
+ void decode(bufferlist::iterator& bl) {
+ DECODE_START(1, bl);
+ ::decode(entries, bl);
+ DECODE_FINISH(bl);
+ }
};
+WRITE_CLASS_ENCODER(RGWSLOInfo)
class RGWPutObj : public RGWOp {
RGWSLOInfo *slo_info;
time_t mtime;
-
uint64_t olh_epoch;
string version_id;
return 0;
}
+template <class T>
+int rgw_rest_get_json_input_keep_data(CephContext *cct, req_state *s, T& out, int max_len, char **pdata, int *len)
+{
+ int rv, data_len;
+ char *data;
+
+ if ((rv = rgw_rest_read_all_input(s, &data, &data_len, max_len)) < 0) {
+ return rv;
+ }
+
+ if (!data_len) {
+ return -EINVAL;
+ }
+
+ *len = data_len;
+
+ JSONParser parser;
+
+ if (!parser.parse(data, data_len)) {
+ free(data);
+ return -EINVAL;
+ }
+
+ decode_json_obj(out, &parser);
+
+ *pdata = data;
+ return 0;
+}
+
class RESTArgs {
public:
uint64_t max_len = s->cct->_conf->rgw_max_slo_entries * MAX_SLO_ENTRY_SIZE;
slo_info = new RGWSLOInfo;
- int r = rgw_rest_get_json_input(s->cct, s, slo_info->entries, max_len, NULL);
+
+ int r = rgw_rest_get_json_input_keep_data(s->cct, s, slo_info->entries, max_len, &slo_info->raw_data, &slo_info->raw_data_len);
if (r < 0) {
ldout(s->cct, 5) << "failed to read input for slo r=" << r << dendl;
return r;
}
- if (slo_info->entries.size() > s->cct->_conf->rgw_max_slo_entries) {
+ if ((int64_t)slo_info->entries.size() > s->cct->_conf->rgw_max_slo_entries) {
ldout(s->cct, 5) << "too many entries in slo request: " << slo_info->entries.size() << dendl;
return -EINVAL;
}
+
+ ofs = slo_info->raw_data_len;
}
return RGWPutObj_ObjStore::get_params();