From dc808953f2f1d12a2bb587f388598ca3e8a0b440 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Thu, 1 Nov 2018 17:54:42 -0700 Subject: [PATCH] rgw: rework lifecycle parsing Use new style xml parsing, instead of inheriting from XMLParser. Signed-off-by: Yehuda Sadeh --- src/common/Formatter.h | 6 + src/rgw/rgw_lc.h | 10 +- src/rgw/rgw_lc_s3.cc | 398 +++++++++++++++++++---------------------- src/rgw/rgw_lc_s3.h | 278 +++------------------------- src/rgw/rgw_op.cc | 23 ++- src/rgw/rgw_rest_s3.cc | 30 ++-- src/rgw/rgw_tag_s3.cc | 79 +++----- src/rgw/rgw_tag_s3.h | 41 ++--- src/rgw/rgw_xml.cc | 14 ++ src/rgw/rgw_xml.h | 16 +- 10 files changed, 317 insertions(+), 578 deletions(-) diff --git a/src/common/Formatter.h b/src/common/Formatter.h index 9d984c11f875..266f00a64364 100644 --- a/src/common/Formatter.h +++ b/src/common/Formatter.h @@ -30,6 +30,9 @@ namespace ceph { ObjectSection(Formatter& f, const char *name) : formatter(f) { formatter.open_object_section(name); } + ObjectSection(Formatter& f, const char *name, const char *ns) : formatter(f) { + formatter.open_object_section_in_ns(name, ns); + } ~ObjectSection() { formatter.close_section(); } @@ -41,6 +44,9 @@ namespace ceph { ArraySection(Formatter& f, const char *name) : formatter(f) { formatter.open_array_section(name); } + ArraySection(Formatter& f, const char *name, const char *ns) : formatter(f) { + formatter.open_array_section_in_ns(name, ns); + } ~ArraySection() { formatter.close_section(); } diff --git a/src/rgw/rgw_lc.h b/src/rgw/rgw_lc.h index bbe855f74cb7..21fd5d5b1516 100644 --- a/src/rgw/rgw_lc.h +++ b/src/rgw/rgw_lc.h @@ -36,7 +36,7 @@ typedef enum { lc_processing, lc_failed, lc_complete, -}LC_BUCKET_STATUS; +} LC_BUCKET_STATUS; class LCExpiration { @@ -46,7 +46,7 @@ protected: string date; public: LCExpiration() {} - ~LCExpiration() {} + LCExpiration(const string& _days, const string& _date) : days(_days), date(_date) {} void encode(bufferlist& bl) const { ENCODE_START(3, 2, bl); @@ -92,7 +92,7 @@ public: return true; } }; -WRITE_CLASS_ENCODER(LCExpiration); +WRITE_CLASS_ENCODER(LCExpiration) class LCTransition { @@ -153,7 +153,7 @@ public: } void dump(Formatter *f) const; }; -WRITE_CLASS_ENCODER(LCTransition); +WRITE_CLASS_ENCODER(LCTransition) class LCFilter { @@ -209,7 +209,7 @@ class LCFilter } void dump(Formatter *f) const; }; -WRITE_CLASS_ENCODER(LCFilter); +WRITE_CLASS_ENCODER(LCFilter) diff --git a/src/rgw/rgw_lc_s3.cc b/src/rgw/rgw_lc_s3.cc index c78851a359f5..c175e2ef54fa 100644 --- a/src/rgw/rgw_lc_s3.cc +++ b/src/rgw/rgw_lc_s3.cc @@ -27,77 +27,100 @@ static bool check_date(const string& _date) return true; } -bool LCExpiration_S3::xml_end(const char * el) { - LCDays_S3 *lc_days = static_cast(find_first("Days")); - LCDeleteMarker_S3 *lc_dm = static_cast(find_first("ExpiredObjectDeleteMarker")); - LCDate_S3 *lc_date = static_cast(find_first("Date")); +void LCExpiration_S3::dump_xml(Formatter *f) const { + if (dm_expiration) { + encode_xml("ExpiredObjectDeleteMarker", "true", f); + } else if (!days.empty()) { + encode_xml("Days", days, f); + } else { + encode_xml("Date", date, f); + } +} - if ((!lc_days && !lc_dm && !lc_date) || (lc_days && lc_dm) - || (lc_days && lc_date) || (lc_dm && lc_date)) { - return false; +void LCExpiration_S3::decode_xml(XMLObj *obj) +{ + bool has_days = RGWXMLDecoder::decode_xml("Days", days, obj); + bool has_date = RGWXMLDecoder::decode_xml("Date", date, obj); + string dm; + bool has_dm = RGWXMLDecoder::decode_xml("ExpiredObjectDeleteMarker", dm, obj); + + if ((!has_days && !has_dm && !has_date) || (has_days && has_dm) + || (has_days && has_date) || (has_dm && has_date)) { + throw RGWXMLDecoder::err("bad Expiration section"); } - if (lc_days) { - days = lc_days->get_data(); - } else if (lc_dm) { - dm_expiration = lc_dm->get_data().compare("true") == 0; - if (!dm_expiration) { - return false; - } - } else { - date = lc_date->get_data(); + + if (has_date && !check_date(date)) { //We need return xml error according to S3 - if (!check_date(date)) { - return false; - } + throw RGWXMLDecoder::err("bad date in Date section"); } - return true; } -bool LCNoncurExpiration_S3::xml_end(const char *el) { - LCDays_S3 *lc_noncur_days = static_cast(find_first("NoncurrentDays")); - if (!lc_noncur_days) { - return false; - } - days = lc_noncur_days->get_data(); - return true; +void LCNoncurExpiration_S3::decode_xml(XMLObj *obj) +{ + RGWXMLDecoder::decode_xml("NoncurrentDays", days, obj, true); } -bool LCMPExpiration_S3::xml_end(const char *el) { - LCDays_S3 *lc_mp_days = static_cast(find_first("DaysAfterInitiation")); - if (!lc_mp_days) { - return false; - } - days = lc_mp_days->get_data(); - return true; +void LCNoncurExpiration_S3::dump_xml(Formatter *f) const +{ + encode_xml("NoncurrentDays", days, f); } -bool RGWLifecycleConfiguration_S3::xml_end(const char *el) { - XMLObjIter iter = find("Rule"); - LCRule_S3 *rule = static_cast(iter.get_next()); - if (!rule) - return false; - while (rule) { - add_rule(rule); - rule = static_cast(iter.get_next()); +void LCMPExpiration_S3::decode_xml(XMLObj *obj) +{ + RGWXMLDecoder::decode_xml("DaysAfterInitiation", days, obj, true); +} + +void LCMPExpiration_S3::dump_xml(Formatter *f) const +{ + encode_xml("DaysAfterInitiation", days, f); +} + +void RGWLifecycleConfiguration_S3::decode_xml(XMLObj *obj) +{ + vector rules; + + RGWXMLDecoder::decode_xml("Rule", rules, obj, true); + + for (auto& rule : rules) { + add_rule(&rule); } + if (cct->_conf->rgw_lc_max_rules < rule_map.size()) { - ldout(cct, 5) << "Warn: The lifecycle config has too many rules, rule number is:" - << rule_map.size() << ", max number is:" << cct->_conf->rgw_lc_max_rules << dendl; - return false; + stringstream ss; + ss << "Warn: The lifecycle config has too many rules, rule number is:" + << rule_map.size() << ", max number is:" << cct->_conf->rgw_lc_max_rules; + throw RGWXMLDecoder::err(ss.str()); } - return true; } -bool LCFilter_S3::xml_end(const char* el) { +void LCFilter_S3::dump_xml(Formatter *f) const +{ + if (has_prefix()) { + encode_xml("Prefix", prefix, f); + } + bool multi = has_multi_condition(); + if (multi) { + f->open_array_section("And"); + } + if (has_tags()) { + const auto& tagset_s3 = static_cast(obj_tags); + tagset_s3.dump_xml(f); + } + if (multi) { + f->close_section(); + } +} - XMLObj *o = find_first("And"); +void LCFilter_S3::decode_xml(XMLObj *obj) +{ + XMLObj *o = obj->find_first("And"); bool single_cond = false; int num_conditions = 0; // If there is an AND condition, every tag is a child of and // else we only support single conditions and return false if we see multiple if (o == nullptr){ - o = this; + o = obj; single_cond = true; } @@ -114,65 +137,56 @@ bool LCFilter_S3::xml_end(const char* el) { num_conditions++; } - return !(single_cond && num_conditions > 1); + if (single_cond && num_conditions > 1) { + throw RGWXMLDecoder::err("Bad filter: badly formed multiple conditions"); + } } -bool LCTransition_S3::xml_end(const char* el) { - LCDays_S3 *lc_days = static_cast(find_first("Days")); - LCDate_S3 *lc_date = static_cast(find_first("Date")); - if ((lc_days && lc_date) || (!lc_days && !lc_date)) { - return false; +void LCTransition_S3::decode_xml(XMLObj *obj) +{ + bool has_days = RGWXMLDecoder::decode_xml("Days", days, obj); + bool has_date = RGWXMLDecoder::decode_xml("Date", date, obj); + if ((has_days && has_date) || (!has_days && !has_date)) { + throw RGWXMLDecoder::err("bad Transition section"); } - if (lc_days) { - days = lc_days->get_data(); - } else { - date = lc_date->get_data(); + + if (has_date && !check_date(date)) { //We need return xml error according to S3 - if (!check_date(date)) { - return false; - } + throw RGWXMLDecoder::err("bad Date in Transition section"); } - LCStorageClass_S3 *lc_storage_class = static_cast(find_first("StorageClass")); - if (!lc_storage_class) { - return false; - } - storage_class = lc_storage_class->get_data(); - if (storage_class.compare("STANDARD_IA") != 0 && storage_class.compare("ONEZONE_IA") != 0 && - storage_class.compare("GLACIER") != 0) { - return false; + + if (!RGWXMLDecoder::decode_xml("StorageClass", storage_class, obj)) { + throw RGWXMLDecoder::err("missing StorageClass in Transition section"); } - return true; } -bool LCNoncurTransition_S3::xml_end(const char* el) { - LCDays_S3 *lc_noncur_days = static_cast(find_first("NoncurrentDays")); - if (!lc_noncur_days) { - return false; +void LCTransition_S3::dump_xml(Formatter *f) const { + if (!days.empty()) { + encode_xml("Days", days, f); + } else { + encode_xml("Date", date, f); } - days = lc_noncur_days->get_data(); - LCStorageClass_S3 *lc_storage_class = static_cast(find_first("StorageClass")); - if (!lc_storage_class) { - return false; + encode_xml("StorageClass", storage_class, f); +} + +void LCNoncurTransition_S3::decode_xml(XMLObj *obj) +{ + if (!RGWXMLDecoder::decode_xml("NoncurrentDays", days, obj)) { + throw RGWXMLDecoder::err("missing NoncurrentDays in NoncurrentVersionTransition section"); } - storage_class = lc_storage_class->get_data(); - if (storage_class.compare("STANDARD_IA") != 0 && storage_class.compare("ONEZONE_IA") != 0 && - storage_class.compare("GLACIER") != 0) { - return false; + if (!RGWXMLDecoder::decode_xml("StorageClass", storage_class, obj)) { + throw RGWXMLDecoder::err("missing StorageClass in NoncurrentVersionTransition section"); } - return true; } +void LCNoncurTransition_S3::dump_xml(Formatter *f) const +{ + encode_xml("NoncurrentDays", days, f); + encode_xml("StorageClass", storage_class, f); +} -bool LCRule_S3::xml_end(const char *el) { - LCID_S3 *lc_id; - LCPrefix_S3 *lc_prefix; - LCStatus_S3 *lc_status; - LCExpiration_S3 *lc_expiration; - LCNoncurExpiration_S3 *lc_noncur_expiration; - LCMPExpiration_S3 *lc_mp_expiration; - LCFilter_S3 *lc_filter; - LCTransition_S3 *lc_transition; - LCNoncurTransition_S3 *lc_noncur_transition; +void LCRule_S3::decode_xml(XMLObj *obj) +{ id.clear(); prefix.clear(); status.clear(); @@ -181,19 +195,12 @@ bool LCRule_S3::xml_end(const char *el) { // S3 generates a 48 bit random ID, maybe we could generate shorter IDs static constexpr auto LC_ID_LENGTH = 48; - lc_id = static_cast(find_first("ID")); - if (lc_id){ - id = lc_id->get_data(); - } else { + if (!RGWXMLDecoder::decode_xml("ID", id, obj)) { gen_rand_alphanumeric_lower(cct, &id, LC_ID_LENGTH); } - - lc_filter = static_cast(find_first("Filter")); - - if (lc_filter){ - filter = *lc_filter; - } else { + LCFilter_S3 filter_s3; + if (!RGWXMLDecoder::decode_xml("Filter", filter_s3, obj)) { // Ideally the following code should be deprecated and we should return // False here, The new S3 LC configuration xml spec. makes Filter mandatory // and Prefix optional. However older clients including boto2 still generate @@ -202,101 +209,103 @@ bool LCRule_S3::xml_end(const char *el) { // argument. A day will come when S3 enforces their own xml-spec, but it is // not this day - lc_prefix = static_cast(find_first("Prefix")); - - if (!lc_prefix){ - return false; + if (!RGWXMLDecoder::decode_xml("Prefix", prefix, obj)) { + throw RGWXMLDecoder::err("missing Prefix in Filter"); } + } + filter = (LCFilter)filter_s3; - prefix = lc_prefix->get_data(); + if (!RGWXMLDecoder::decode_xml("Status", status, obj)) { + throw RGWXMLDecoder::err("missing Status in Filter"); + } + if (status.compare("Enabled") != 0 && status.compare("Disabled") != 0) { + throw RGWXMLDecoder::err("bad Status in Filter"); } - lc_status = static_cast(find_first("Status")); - if (!lc_status) - return false; - status = lc_status->get_data(); - if (status.compare("Enabled") != 0 && status.compare("Disabled") != 0) - return false; + LCExpiration_S3 s3_expiration; + LCExpiration_S3 s3_noncur_expiration; + LCExpiration_S3 s3_mp_expiration; + LCFilter_S3 s3_filter; - lc_expiration = static_cast(find_first("Expiration")); - lc_noncur_expiration = static_cast(find_first("NoncurrentVersionExpiration")); - lc_mp_expiration = static_cast(find_first("AbortIncompleteMultipartUpload")); + bool has_expiration = RGWXMLDecoder::decode_xml("Expiration", s3_expiration, obj); + bool has_noncur_expiration = RGWXMLDecoder::decode_xml("NoncurrentVersionExpiration", s3_noncur_expiration, obj); + bool has_mp_expiration = RGWXMLDecoder::decode_xml("AbortIncompleteMultipartUpload", s3_mp_expiration, obj); - XMLObjIter iter = find("Transition"); - lc_transition = static_cast(iter.get_next()); - XMLObjIter noncur_iter = find("NoncurrentVersionTransition"); - lc_noncur_transition = static_cast(noncur_iter.get_next()); + vector transitions; + vector noncur_transitions; - if (!lc_expiration && !lc_noncur_expiration && !lc_mp_expiration && !lc_transition && !lc_noncur_transition) { - return false; - } else { - if (lc_expiration) { - if (lc_expiration->has_days()) { - expiration.set_days(lc_expiration->get_days_str()); - } else if (lc_expiration->has_date()) { - expiration.set_date(lc_expiration->get_date()); - } else { - dm_expiration = lc_expiration->get_dm_expiration(); - } - } - if (lc_noncur_expiration) { - noncur_expiration = *lc_noncur_expiration; - } - if (lc_mp_expiration) { - mp_expiration = *lc_mp_expiration; + bool has_transition = RGWXMLDecoder::decode_xml("Transition", transitions, obj); + bool has_noncur_transition = RGWXMLDecoder::decode_xml("NoncurrentVersionTransition", noncur_transitions, obj); + + if (!has_expiration && + !has_noncur_expiration && + !has_mp_expiration && + !has_transition && + !has_noncur_transition) { + throw RGWXMLDecoder::err("bad Rule"); + } + + if (has_expiration) { + if (s3_expiration.has_days() || + s3_expiration.has_date()) { + expiration = s3_expiration; + } else { + dm_expiration = s3_expiration.get_dm_expiration(); } - while (lc_transition) { - if (!add_transition(lc_transition)) { - return false; - } - lc_transition = static_cast(iter.get_next()); + } + if (has_noncur_expiration) { + noncur_expiration = s3_noncur_expiration; + } + if (has_mp_expiration) { + mp_expiration = s3_mp_expiration; + } + for (auto& t : transitions) { + if (!add_transition(&t)) { + throw RGWXMLDecoder::err("Failed to add transition"); } - while (lc_noncur_transition) { - if (!add_noncur_transition(lc_noncur_transition)) { - return false; - } - lc_noncur_transition = static_cast(noncur_iter.get_next()); + } + for (auto& t : noncur_transitions) { + if (!add_noncur_transition(&t)) { + throw RGWXMLDecoder::err("Failed to add non-current version transition"); } } - return true; } -void LCRule_S3::to_xml(ostream& out) { - out << "" ; - out << "" << id << ""; +void LCRule_S3::dump_xml(Formatter *f) const { + encode_xml("ID", id, f); + // In case of an empty filter and an empty Prefix, we defer to Prefix. if (!filter.empty()) { - LCFilter_S3& lc_filter = static_cast(filter); - lc_filter.to_xml(out); + const LCFilter_S3& lc_filter = static_cast(filter); + encode_xml("Filter", lc_filter, f); } else { - out << "" << prefix << ""; + encode_xml("Prefix", prefix, f); } - out << "" << status << ""; + encode_xml("Status", status, f); if (!expiration.empty() || dm_expiration) { LCExpiration_S3 expir(expiration.get_days_str(), expiration.get_date(), dm_expiration); - expir.to_xml(out); + encode_xml("Expiration", expir, f); } if (!noncur_expiration.empty()) { - LCNoncurExpiration_S3& noncur_expir = static_cast(noncur_expiration); - noncur_expir.to_xml(out); + const LCNoncurExpiration_S3& noncur_expir = static_cast(noncur_expiration); + encode_xml("NoncurrentVersionExpiration", noncur_expir, f); } if (!mp_expiration.empty()) { - LCMPExpiration_S3& mp_expir = static_cast(mp_expiration); - mp_expir.to_xml(out); + const LCMPExpiration_S3& mp_expir = static_cast(mp_expiration); + encode_xml("AbortIncompleteMultipartUpload", mp_expir, f); } if (!transitions.empty()) { for (auto &elem : transitions) { - LCTransition_S3& tran = static_cast(elem.second); - tran.to_xml(out); + const LCTransition_S3& tran = static_cast(elem.second); + encode_xml("Transition", tran, f); } } if (!noncur_transitions.empty()) { for (auto &elem : noncur_transitions) { - LCNoncurTransition_S3& noncur_tran = static_cast(elem.second); - noncur_tran.to_xml(out); + const LCNoncurTransition_S3& noncur_tran = static_cast(elem.second); + encode_xml("NoncurrentVersionTransition", noncur_tran, f); } } - out << ""; } int RGWLifecycleConfiguration_S3::rebuild(RGWRados *store, RGWLifecycleConfiguration& dest) @@ -316,58 +325,11 @@ int RGWLifecycleConfiguration_S3::rebuild(RGWRados *store, RGWLifecycleConfigura } - void RGWLifecycleConfiguration_S3::dump_xml(Formatter *f) const { - f->open_object_section_in_ns("LifecycleConfiguration", XMLNS_AWS_S3); - - for (auto iter = rule_map.begin(); iter != rule_map.end(); ++iter) { - const LCRule_S3& rule = static_cast(iter->second); - rule.dump_xml(f); - } - - f->close_section(); // Lifecycle -} - -XMLObj *RGWLCXMLParser_S3::alloc_obj(const char *el) -{ - XMLObj * obj = NULL; - if (strcmp(el, "LifecycleConfiguration") == 0) { - obj = new RGWLifecycleConfiguration_S3(cct); - } else if (strcmp(el, "Rule") == 0) { - obj = new LCRule_S3(cct); - } else if (strcmp(el, "ID") == 0) { - obj = new LCID_S3(); - } else if (strcmp(el, "Prefix") == 0) { - obj = new LCPrefix_S3(); - } else if (strcmp(el, "Filter") == 0) { - obj = new LCFilter_S3(); - } else if (strcmp(el, "Status") == 0) { - obj = new LCStatus_S3(); - } else if (strcmp(el, "Expiration") == 0) { - obj = new LCExpiration_S3(); - } else if (strcmp(el, "Days") == 0) { - obj = new LCDays_S3(); - } else if (strcmp(el, "Date") == 0) { - obj = new LCDate_S3(); - } else if (strcmp(el, "ExpiredObjectDeleteMarker") == 0) { - obj = new LCDeleteMarker_S3(); - } else if (strcmp(el, "NoncurrentVersionExpiration") == 0) { - obj = new LCNoncurExpiration_S3(); - } else if (strcmp(el, "NoncurrentDays") == 0) { - obj = new LCDays_S3(); - } else if (strcmp(el, "AbortIncompleteMultipartUpload") == 0) { - obj = new LCMPExpiration_S3(); - } else if (strcmp(el, "DaysAfterInitiation") == 0) { - obj = new LCDays_S3(); - } else if (strcmp(el, "StorageClass") == 0) { - obj = new LCStorageClass_S3(); - } else if (strcmp(el, "Transition") == 0) { - obj = new LCTransition_S3(); - } else if (strcmp(el, "NoncurrentVersionTransition") == 0) { - obj = new LCNoncurTransition_S3(); - } - return obj; + for (auto iter = rule_map.begin(); iter != rule_map.end(); ++iter) { + const LCRule_S3& rule = static_cast(iter->second); + encode_xml("Rule", rule, f); + } } - diff --git a/src/rgw/rgw_lc_s3.h b/src/rgw/rgw_lc_s3.h index e9815e2fc3ea..8fbeba8df732 100644 --- a/src/rgw/rgw_lc_s3.h +++ b/src/rgw/rgw_lc_s3.h @@ -14,134 +14,23 @@ #include "rgw_xml.h" #include "rgw_tag_s3.h" -class LCID_S3 : public XMLObj +class LCFilter_S3 : public LCFilter { public: - LCID_S3() {} - ~LCID_S3() override {} - string& to_str() { return data; } -}; - -class LCPrefix_S3 : public XMLObj -{ -public: - LCPrefix_S3() {} - ~LCPrefix_S3() override {} - string& to_str() { return data; } -}; - -class LCFilter_S3 : public LCFilter, public XMLObj -{ - public: - ~LCFilter_S3() override {} - string& to_str() { return data; } - void to_xml(ostream& out){ - out << ""; - stringstream ss; - if (has_prefix()) - out << "" << prefix << ""; - if (has_tags()){ - for (const auto&kv : obj_tags.get_tags()){ - ss << ""; - ss << "" << kv.first << ""; - ss << "" << kv.second << ""; - ss << ""; - } - } - - if (has_multi_condition()) { - out << "" << ss.str() << ""; - } else { - out << ss.str(); - } - - out << ""; - } - void dump_xml(Formatter *f) const { - f->open_object_section("Filter"); - if (has_multi_condition()) - f->open_object_section("And"); - if (!prefix.empty()) - encode_xml("Prefix", prefix, f); - if (has_tags()){ - const auto& tagset_s3 = static_cast(obj_tags); - tagset_s3.dump_xml(f); - } - if (has_multi_condition()) - f->close_section(); // And; - f->close_section(); // Filter - } - bool xml_end(const char *el) override; -}; - -class LCStatus_S3 : public XMLObj -{ -public: - LCStatus_S3() {} - ~LCStatus_S3() override {} - string& to_str() { return data; } -}; - -class LCDays_S3 : public XMLObj -{ -public: - LCDays_S3() {} - ~LCDays_S3() override {} - string& to_str() { return data; } -}; - -class LCDate_S3 : public XMLObj -{ -public: - LCDate_S3() {} - ~LCDate_S3() override {} - string& to_str() { return data; } -}; - -class LCDeleteMarker_S3 : public XMLObj -{ -public: - LCDeleteMarker_S3() {} - ~LCDeleteMarker_S3() override {} - string& to_str() { return data; } + void dump_xml(Formatter *f) const; + void decode_xml(XMLObj *obj); }; -class LCExpiration_S3 : public LCExpiration, public XMLObj +class LCExpiration_S3 : public LCExpiration { private: - bool dm_expiration; + bool dm_expiration{false}; public: - LCExpiration_S3(): dm_expiration(false) {} - LCExpiration_S3(string _days, string _date, bool _dm_expiration) { - days = _days; - date = _date; - dm_expiration = _dm_expiration; - } - ~LCExpiration_S3() override {} + LCExpiration_S3() {} + LCExpiration_S3(string _days, string _date, bool _dm_expiration) : LCExpiration(_days, _date), dm_expiration(_dm_expiration) {} - bool xml_end(const char *el) override; - void to_xml(ostream& out) { - out << ""; - if (dm_expiration) { - out << "" << "true" << ""; - } else if (!days.empty()){ - out << "" << days << ""; - } else { - out << "" << date << ""; - } - out << ""; - } - void dump_xml(Formatter *f) const { - f->open_object_section("Expiration"); - if (dm_expiration) { - encode_xml("ExpiredObjectDeleteMarker", "true", f); - } else if (!days.empty()) { - encode_xml("Days", days, f); - } else { - encode_xml("Date", date, f); - } - f->close_section(); // Expiration - } + void dump_xml(Formatter *f) const; + void decode_xml(XMLObj *obj); void set_dm_expiration(bool _dm_expiration) { dm_expiration = _dm_expiration; @@ -152,180 +41,67 @@ public: } }; -class LCNoncurExpiration_S3 : public LCExpiration, public XMLObj +class LCNoncurExpiration_S3 : public LCExpiration { public: LCNoncurExpiration_S3() {} - ~LCNoncurExpiration_S3() override {} - bool xml_end(const char *el) override; - void to_xml(ostream& out) { - out << "" << "" << days << ""<< ""; - } - void dump_xml(Formatter *f) const { - f->open_object_section("NoncurrentVersionExpiration"); - encode_xml("NoncurrentDays", days, f); - f->close_section(); - } + void decode_xml(XMLObj *obj); + void dump_xml(Formatter *f) const; }; -class LCMPExpiration_S3 : public LCExpiration, public XMLObj +class LCMPExpiration_S3 : public LCExpiration { public: LCMPExpiration_S3() {} - ~LCMPExpiration_S3() {} - bool xml_end(const char *el) override; - void to_xml(ostream& out) { - out << "" << "" << days << "" << ""; - } - void dump_xml(Formatter *f) const { - f->open_object_section("AbortIncompleteMultipartUpload"); - encode_xml("DaysAfterInitiation", days, f); - f->close_section(); - } -}; - -class LCStorageClass_S3 : public XMLObj -{ -public: - LCStorageClass_S3() {} - ~LCStorageClass_S3() override {} - string& to_str() { return data; } + void decode_xml(XMLObj *obj); + void dump_xml(Formatter *f) const; }; -class LCTransition_S3 : public LCTransition, public XMLObj +class LCTransition_S3 : public LCTransition { public: LCTransition_S3() {} - ~LCTransition_S3() {} - bool xml_end(const char *el) override; - void to_xml(ostream& out) { - out << ""; - if (!days.empty()) { - out << "" << days << ""; - } else { - out << "" << date << ""; - } - out << "" << storage_class << "" << ""; - } - - void dump_xml(Formatter *f) const { - f->open_object_section("Transition"); - if (!days.empty()) { - encode_xml("Days", days, f); - } else { - encode_xml("Date", date, f); - } - encode_xml("StorageClass", storage_class, f); - f->close_section(); - } + void decode_xml(XMLObj *obj); + void dump_xml(Formatter *f) const; }; -class LCNoncurTransition_S3 : public LCTransition, public XMLObj +class LCNoncurTransition_S3 : public LCTransition { public: LCNoncurTransition_S3() {} ~LCNoncurTransition_S3() {} - bool xml_end(const char *el) override; - void to_xml(ostream& out) { - out << "" << "" << days << "" - << "" << storage_class << "" << ""; - } - - void dump_xml(Formatter *f) const { - f->open_object_section("NoncurrentVersionTransition"); - encode_xml("NoncurrentDays", days, f); - encode_xml("StorageClass", storage_class, f); - f->close_section(); - } + void decode_xml(XMLObj *obj); + void dump_xml(Formatter *f) const; }; -class LCRule_S3 : public LCRule, public XMLObj +class LCRule_S3 : public LCRule { private: CephContext *cct; public: LCRule_S3(): cct(nullptr) {} explicit LCRule_S3(CephContext *_cct): cct(_cct) {} - ~LCRule_S3() override {} - void to_xml(ostream& out); - bool xml_end(const char *el) override; - bool xml_start(const char *el, const char **attr); - void dump_xml(Formatter *f) const { - f->open_object_section("Rule"); - encode_xml("ID", id, f); - // In case of an empty filter and an empty Prefix, we defer to Prefix. - if (!filter.empty()) { - const LCFilter_S3& lc_filter = static_cast(filter); - lc_filter.dump_xml(f); - } else { - encode_xml("Prefix", prefix, f); - } - encode_xml("Status", status, f); - if (!expiration.empty() || dm_expiration) { - LCExpiration_S3 expir(expiration.get_days_str(), expiration.get_date(), dm_expiration); - expir.dump_xml(f); - } - if (!noncur_expiration.empty()) { - const LCNoncurExpiration_S3& noncur_expir = static_cast(noncur_expiration); - noncur_expir.dump_xml(f); - } - if (!mp_expiration.empty()) { - const LCMPExpiration_S3& mp_expir = static_cast(mp_expiration); - mp_expir.dump_xml(f); - } - if (!transitions.empty()) { - for (auto &elem : transitions) { - const LCTransition_S3& tran = static_cast(elem.second); - tran.dump_xml(f); - } - } - if (!noncur_transitions.empty()) { - for (auto &elem : noncur_transitions) { - const LCNoncurTransition_S3& noncur_tran = static_cast(elem.second); - noncur_tran.dump_xml(f); - } - } - f->close_section(); // Rule - } + void dump_xml(Formatter *f) const; + void decode_xml(XMLObj *obj); void set_ctx(CephContext *ctx) { cct = ctx; } }; -class RGWLCXMLParser_S3 : public RGWXMLParser -{ - CephContext *cct; - - XMLObj *alloc_obj(const char *el) override; -public: - explicit RGWLCXMLParser_S3(CephContext *_cct) : cct(_cct) {} -}; - -class RGWLifecycleConfiguration_S3 : public RGWLifecycleConfiguration, public XMLObj +class RGWLifecycleConfiguration_S3 : public RGWLifecycleConfiguration { public: explicit RGWLifecycleConfiguration_S3(CephContext *_cct) : RGWLifecycleConfiguration(_cct) {} - RGWLifecycleConfiguration_S3() : RGWLifecycleConfiguration(NULL) {} - ~RGWLifecycleConfiguration_S3() override {} - - bool xml_end(const char *el) override; + RGWLifecycleConfiguration_S3() : RGWLifecycleConfiguration(nullptr) {} - void to_xml(ostream& out) { - out << ""; - multimap::iterator iter; - for (iter = rule_map.begin(); iter != rule_map.end(); ++iter) { - LCRule_S3& rule = static_cast(iter->second); - rule.to_xml(out); - } - out << ""; - } + void decode_xml(XMLObj *obj); int rebuild(RGWRados *store, RGWLifecycleConfiguration& dest); void dump_xml(Formatter *f) const; }; diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index fea79e9cecfd..71caf89b4088 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -5118,8 +5118,8 @@ void RGWPutLC::execute() { bufferlist bl; - RGWLifecycleConfiguration_S3 *config = NULL; - RGWLCXMLParser_S3 parser(s->cct); + RGWLifecycleConfiguration_S3 config; + RGWXMLParser parser; RGWLifecycleConfiguration_S3 new_config(s->cct); content_md5 = s->info.env->get("HTTP_CONTENT_MD5"); @@ -5172,20 +5172,25 @@ void RGWPutLC::execute() op_ret = -ERR_MALFORMED_XML; return; } - config = static_cast(parser.find_first("LifecycleConfiguration")); - if (!config) { - op_ret = -ERR_MALFORMED_XML; + + try { + RGWXMLDecoder::decode_xml("LifecycleConfiguration", config, &parser); + } catch (RGWXMLDecoder::err& err) { + ldpp_dout(this, 5) << "Bad lifecycle configuration: " << err << dendl; + op_ret = -EINVAL; return; } - op_ret = config->rebuild(store, new_config); + op_ret = config.rebuild(store, new_config); if (op_ret < 0) return; if (s->cct->_conf->subsys.should_gather()) { - ldpp_dout(this, 15) << "New LifecycleConfiguration:"; - new_config.to_xml(*_dout); - *_dout << dendl; + XMLFormatter xf; + new_config.dump_xml(&xf); + stringstream ss; + xf.flush(ss); + ldpp_dout(this, 15) << "New LifecycleConfiguration:" << ss.str() << dendl; } op_ret = store->get_lc()->set_bucket_config(s->bucket_info, s->bucket_attrs, &new_config); diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index c87b0cb13d34..c65175788db8 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -402,7 +402,7 @@ void RGWGetObjTags_ObjStore_S3::send_response_data(bufferlist& bl) int RGWPutObjTags_ObjStore_S3::get_params() { - RGWObjTagsXMLParser parser; + RGWXMLParser parser; if (!parser.init()){ return -EINVAL; @@ -421,17 +421,17 @@ int RGWPutObjTags_ObjStore_S3::get_params() return -ERR_MALFORMED_XML; } - RGWObjTagSet_S3 *obj_tags_s3; - RGWObjTagging_S3 *tagging; + RGWObjTagging_S3 tagging; - tagging = static_cast(parser.find_first("Tagging")); - obj_tags_s3 = static_cast(tagging->find_first("TagSet")); - if(!obj_tags_s3){ + try { + RGWXMLDecoder::decode_xml("Tagging", tagging, &parser); + } catch (RGWXMLDecoder::err& err) { + ldout(s->cct, 5) << "Malformed tagging request: " << err << dendl; return -ERR_MALFORMED_XML; } RGWObjTags obj_tags; - r = obj_tags_s3->rebuild(obj_tags); + r = tagging.rebuild(obj_tags); if (r < 0) return r; @@ -1758,7 +1758,7 @@ int RGWPostObj_ObjStore_S3::get_tags() { string tags_str; if (part_str(parts, "tagging", &tags_str)) { - RGWObjTagsXMLParser parser; + RGWXMLParser parser; if (!parser.init()){ ldout(s->cct, 0) << "Couldn't init RGWObjTags XML parser" << dendl; err_msg = "Server couldn't process the request"; @@ -1770,17 +1770,17 @@ int RGWPostObj_ObjStore_S3::get_tags() return -EINVAL; } - RGWObjTagSet_S3 *obj_tags_s3; - RGWObjTagging_S3 *tagging; + RGWObjTagging_S3 tagging; - tagging = static_cast(parser.find_first("Tagging")); - obj_tags_s3 = static_cast(tagging->find_first("TagSet")); - if(!obj_tags_s3){ - return -ERR_MALFORMED_XML; + try { + RGWXMLDecoder::decode_xml("Tagging", tagging, &parser); + } catch (RGWXMLDecoder::err& err) { + ldout(s->cct, 5) << "Malformed tagging request: " << err << dendl; + return -EINVAL; } RGWObjTags obj_tags; - int r = obj_tags_s3->rebuild(obj_tags); + int r = tagging.rebuild(obj_tags); if (r < 0) return r; diff --git a/src/rgw/rgw_tag_s3.cc b/src/rgw/rgw_tag_s3.cc index d9f52b7af857..c5ad87caed60 100644 --- a/src/rgw/rgw_tag_s3.cc +++ b/src/rgw/rgw_tag_s3.cc @@ -9,43 +9,41 @@ #include "rgw_tag_s3.h" -bool RGWObjTagEntry_S3::xml_end(const char*){ - RGWObjTagKey_S3 *key_obj = static_cast(find_first("Key")); - RGWObjTagValue_S3 *val_obj = static_cast(find_first("Value")); +void RGWObjTagEntry_S3::decode_xml(XMLObj *obj) { + RGWXMLDecoder::decode_xml("Key", key, obj, true); + RGWXMLDecoder::decode_xml("Value", val, obj, true); +} - if (!key_obj) - return false; +void RGWObjTagEntry_S3::dump_xml(Formatter *f) const { + encode_xml("Key", key, f); + encode_xml("Value", val, f); - string s = key_obj->get_data(); - if (s.empty()){ - return false; + if (key.empty()) { + throw RGWXMLDecoder::err("empty key"); } - key = s; - if (val_obj) { - val = val_obj->get_data(); + if (val.empty()) { + throw RGWXMLDecoder::err("empty val"); } - - return true; } -bool RGWObjTagSet_S3::xml_end(const char*){ - XMLObjIter iter = find("Tag"); - RGWObjTagEntry_S3 *tagentry = static_cast(iter.get_next()); - while (tagentry) { - const std::string& key = tagentry->get_key(); - const std::string& val = tagentry->get_val(); - if (!add_tag(key,val)) - return false; +void RGWObjTagSet_S3::decode_xml(XMLObj *obj) { + vector entries; - tagentry = static_cast(iter.get_next()); + RGWXMLDecoder::decode_xml("Tag", entries, obj, true); + + for (auto& entry : entries) { + const std::string& key = entry.get_key(); + const std::string& val = entry.get_val(); + if (!add_tag(key,val)) { + throw RGWXMLDecoder::err("failed to add tag"); + } } - return true; } -int RGWObjTagSet_S3::rebuild(RGWObjTags& dest){ +int RGWObjTagSet_S3::rebuild(RGWObjTags& dest) { int ret; - for (const auto &it: tag_map){ + for (const auto &it : tag_map){ ret = dest.check_and_add_tag(it.first, it.second); if (ret < 0) return ret; @@ -53,34 +51,15 @@ int RGWObjTagSet_S3::rebuild(RGWObjTags& dest){ return 0; } -bool RGWObjTagging_S3::xml_end(const char*){ - RGWObjTagSet_S3 *tagset = static_cast (find_first("TagSet")); - return tagset != nullptr; - +void RGWObjTagging_S3::decode_xml(XMLObj *obj) { + RGWXMLDecoder::decode_xml("TagSet", tagset, obj, true); } void RGWObjTagSet_S3::dump_xml(Formatter *f) const { - for (const auto& tag: tag_map){ - f->open_object_section("Tag"); - f->dump_string("Key", tag.first); - f->dump_string("Value", tag.second); - f->close_section(); + for (const auto& tag : tag_map){ + Formatter::ObjectSection os(*f, "Tag"); + encode_xml("Key", tag.first, f); + encode_xml("Value", tag.second, f); } } -XMLObj *RGWObjTagsXMLParser::alloc_obj(const char *el){ - XMLObj* obj = nullptr; - if(strcmp(el,"Tagging") == 0) { - obj = new RGWObjTagging_S3(); - } else if (strcmp(el,"TagSet") == 0) { - obj = new RGWObjTagSet_S3(); - } else if (strcmp(el,"Tag") == 0) { - obj = new RGWObjTagEntry_S3(); - } else if (strcmp(el,"Key") == 0) { - obj = new RGWObjTagKey_S3(); - } else if (strcmp(el,"Value") == 0) { - obj = new RGWObjTagValue_S3(); - } - - return obj; -} diff --git a/src/rgw/rgw_tag_s3.h b/src/rgw/rgw_tag_s3.h index 8afca46d2c70..7ed022776d8f 100644 --- a/src/rgw/rgw_tag_s3.h +++ b/src/rgw/rgw_tag_s3.h @@ -14,15 +14,7 @@ #include "rgw_tag.h" #include "rgw_xml.h" -struct RGWObjTagKey_S3: public XMLObj -{ -}; - -struct RGWObjTagValue_S3: public XMLObj -{ -}; - -class RGWObjTagEntry_S3: public XMLObj +class RGWObjTagEntry_S3 { std::string key; std::string val; @@ -31,32 +23,31 @@ public: RGWObjTagEntry_S3(const std::string &k, const std::string &v):key(k),val(v) {}; ~RGWObjTagEntry_S3() {} - bool xml_end(const char*) override; - const std::string& get_key () const { return key;} - const std::string& get_val () const { return val;} - //void to_xml(CephContext *cct, ostream& out) const; -}; + const std::string& get_key () const { return key; } + const std::string& get_val () const { return val; } -class RGWObjTagSet_S3: public RGWObjTags, public XMLObj -{ -public: - bool xml_end(const char*) override; void dump_xml(Formatter *f) const; - int rebuild(RGWObjTags& dest); + void decode_xml(XMLObj *obj); }; -class RGWObjTagging_S3: public XMLObj +class RGWObjTagSet_S3: public RGWObjTags { public: - bool xml_end(const char*) override; + int rebuild(RGWObjTags& dest); + + void dump_xml(Formatter *f) const; + void decode_xml(XMLObj *obj); }; -class RGWObjTagsXMLParser : public RGWXMLParser +class RGWObjTagging_S3 { - XMLObj *alloc_obj(const char *el) override; + RGWObjTagSet_S3 tagset; public: - RGWObjTagsXMLParser() {} - ~RGWObjTagsXMLParser() {} + void decode_xml(XMLObj *obj); + int rebuild(RGWObjTags& dest) { + return tagset.rebuild(dest); + } }; + #endif /* RGW_TAG_S3_H */ diff --git a/src/rgw/rgw_xml.cc b/src/rgw/rgw_xml.cc index a1e85bac8b20..cc85286355f9 100755 --- a/src/rgw/rgw_xml.cc +++ b/src/rgw/rgw_xml.cc @@ -120,6 +120,20 @@ find(string name) return iter; } +XMLObjIter XMLObj::find_first() +{ + XMLObjIter iter; + map::iterator first; + map::iterator last; + first = children.begin(); + if (first != children.end()) { + last = children.upper_bound(first->first); + }else + last = children.end(); + iter.set(first, last); + return iter; +} + XMLObj *XMLObj:: find_first(string name) { diff --git a/src/rgw/rgw_xml.h b/src/rgw/rgw_xml.h index 00425cd583bb..38b2c702ecfd 100644 --- a/src/rgw/rgw_xml.h +++ b/src/rgw/rgw_xml.h @@ -51,6 +51,7 @@ public: void add_child(string el, XMLObj *obj); bool get_attr(string name, string& attr); XMLObjIter find(string name); + XMLObjIter find_first(); XMLObj *find_first(string name); friend ostream& operator<<(ostream &out, const XMLObj &obj); @@ -117,6 +118,11 @@ public: static void decode_xml(const char *name, T& val, T& default_val, XMLObj *obj); }; +static inline ostream& operator<<(ostream &out, RGWXMLDecoder::err& err) +{ + return out << err.message; +} + template void decode_xml_obj(T& val, XMLObj *obj) { @@ -155,17 +161,17 @@ void do_decode_xml_obj(list& l, const string& name, XMLObj *obj) } template -void do_decode_xml_obj(vector& l, const string& name, XMLObj *obj) +void decode_xml_obj(std::vector& v, XMLObj *obj) { - l.clear(); + v.clear(); - XMLObjIter iter = obj->find(name); + XMLObjIter iter = obj->find_first(); XMLObj *o; - while (o = iter.get_next()) { + while ((o = iter.get_next())) { T val; decode_xml_obj(val, o); - l.push_back(val); + v.push_back(val); } } -- 2.47.3