if (id.length() > MAX_ID_LEN) {
return false;
}
- else if(expiration.empty() && noncur_expiration.empty() && mp_expiration.empty() && !dm_expiration) {
+ else if(expiration.empty() && noncur_expiration.empty() && mp_expiration.empty() && !dm_expiration &&
+ transitions.empty() && noncur_transitions.empty()) {
return false;
}
else if (!expiration.valid() || !noncur_expiration.valid() || !mp_expiration.valid()) {
return false;
}
+ if (!transitions.empty()) {
+ bool using_days = expiration.has_days();
+ bool using_date = expiration.has_date();
+ for (const auto& elem : transitions) {
+ if (!elem.second.valid()) {
+ return false;
+ }
+ using_days = using_days || elem.second.has_days();
+ using_date = using_date || elem.second.has_date();
+ if (using_days && using_date) {
+ return false;
+ }
+ }
+ }
+ for (const auto& elem : noncur_transitions) {
+ if (!elem.second.valid()) {
+ return false;
+ }
+ }
+
return true;
}
op.mp_expiration = rule->get_mp_expiration().get_days();
}
op.dm_expiration = rule->get_dm_expiration();
-
+ for (const auto &elem : rule->get_transitions()) {
+ transition_action action;
+ if (elem.second.has_days()) {
+ action.days = elem.second.get_days();
+ } else {
+ action.date = ceph::from_iso_8601(elem.second.get_date());
+ }
+ action.storage_class = elem.first;
+ op.transitions.emplace(action.storage_class, std::move(action));
+ }
+ for (const auto &elem : rule->get_noncur_transitions()) {
+ transition_action action;
+ action.days = elem.second.get_days();
+ action.date = ceph::from_iso_8601(elem.second.get_date());
+ action.storage_class = elem.first;
+ op.noncur_transitions.emplace(action.storage_class, std::move(action));
+ }
std::string prefix;
if (rule->get_filter().has_prefix()){
prefix = rule->get_filter().get_prefix();
return true;
} else if (first.mp_expiration > 0 && second.mp_expiration > 0) {
return true;
- } else {
- return false;
+ } else if (!first.transitions.empty() && !second.transitions.empty()) {
+ for (auto &elem : first.transitions) {
+ if (second.transitions.find(elem.first) != second.transitions.end()) {
+ return true;
+ }
+ }
+ } else if (!first.noncur_transitions.empty() && !second.noncur_transitions.empty()) {
+ for (auto &elem : first.noncur_transitions) {
+ if (second.noncur_transitions.find(elem.first) != second.noncur_transitions.end()) {
+ return true;
+ }
+ }
}
+ return false;
}
//Rules are conflicted: if one rule's prefix starts with other rule's prefix, and these two rules
lc_complete,
}LC_BUCKET_STATUS;
+typedef enum {
+ standard_ia = 0,
+ onezone_ia,
+ glacier,
+ undefined,
+} STORAGE_CLASS;
+
class LCExpiration
{
protected:
return true;
}
};
-WRITE_CLASS_ENCODER(LCExpiration)
+WRITE_CLASS_ENCODER(LCExpiration);
+
+class LCTransition
+{
+protected:
+ string days;
+ string date;
+ string storage_class;
+
+public:
+ int get_days() const {
+ return atoi(days.c_str());
+ }
+
+ string get_date() const {
+ return date;
+ }
+
+ string get_storage_class_str() const {
+ return storage_class;
+ }
+
+ STORAGE_CLASS get_storage_class() const {
+ if (storage_class.compare("STANDARD_IA") == 0) {
+ return standard_ia;
+ } else if (storage_class.compare("ONEZONE_IA") == 0) {
+ return onezone_ia;
+ } else if (storage_class.compare("GLACIER") == 0) {
+ return glacier;
+ } else {
+ return undefined;
+ }
+ }
+
+ bool has_days() const {
+ return !days.empty();
+ }
+
+ bool has_date() const {
+ return !date.empty();
+ }
+
+ bool empty() const {
+ return days.empty() && date.empty();
+ }
+
+ bool valid() const {
+ if (!days.empty() && !date.empty()) {
+ return false;
+ } else if (!days.empty() && get_days() <=0) {
+ return false;
+ }
+ //We've checked date in xml parsing
+ return true;
+ }
+
+ void encode(bufferlist& bl) const {
+ ENCODE_START(1, 1, bl);
+ encode(days, bl);
+ encode(date, bl);
+ encode(storage_class, bl);
+ ENCODE_FINISH(bl);
+ }
+
+ void decode(bufferlist::const_iterator& bl) {
+ DECODE_START(1, bl);
+ decode(days, bl);
+ decode(date, bl);
+ decode(storage_class, bl);
+ DECODE_FINISH(bl);
+ }
+ void dump(Formatter *f) const;
+};
+WRITE_CLASS_ENCODER(LCTransition);
class LCFilter
{
LCExpiration noncur_expiration;
LCExpiration mp_expiration;
LCFilter filter;
+ map<int, LCTransition> transitions;
+ map<int, LCTransition> noncur_transitions;
bool dm_expiration = false;
public:
return dm_expiration;
}
+ map<int, LCTransition>& get_transitions() {
+ return transitions;
+ }
+
+ map<int, LCTransition>& get_noncur_transitions() {
+ return noncur_transitions;
+ }
+
void set_id(const string& _id) {
id = _id;
}
dm_expiration = _dm_expiration;
}
+ bool add_transition(LCTransition* _transition) {
+ auto ret = transitions.emplace(_transition->get_storage_class(), *_transition);
+ return ret.second;
+ }
+
+ bool add_noncur_transition(LCTransition* _noncur_transition) {
+ auto ret = noncur_transitions.emplace(_noncur_transition->get_storage_class(), *_noncur_transition);
+ return ret.second;
+ }
+
bool valid();
void encode(bufferlist& bl) const {
- ENCODE_START(5, 1, bl);
+ ENCODE_START(6, 1, bl);
encode(id, bl);
encode(prefix, bl);
encode(status, bl);
encode(mp_expiration, bl);
encode(dm_expiration, bl);
encode(filter, bl);
+ encode(transitions, bl);
+ encode(noncur_transitions, bl);
ENCODE_FINISH(bl);
}
void decode(bufferlist::const_iterator& bl) {
- DECODE_START_LEGACY_COMPAT_LEN(5, 1, 1, bl);
+ DECODE_START_LEGACY_COMPAT_LEN(6, 1, 1, bl);
decode(id, bl);
decode(prefix, bl);
decode(status, bl);
if (struct_v >= 5) {
decode(filter, bl);
}
+ if (struct_v >= 6) {
+ decode(transitions, bl);
+ decode(noncur_transitions, bl);
+ }
DECODE_FINISH(bl);
}
void dump(Formatter *f) const;
};
WRITE_CLASS_ENCODER(LCRule)
+struct transition_action
+{
+ int days;
+ boost::optional<ceph::real_time> date;
+ int storage_class;
+ transition_action() : days(0), storage_class(standard_ia) {}
+};
+
struct lc_op
{
bool status{false};
int mp_expiration{0};
boost::optional<ceph::real_time> expiration_date;
boost::optional<RGWObjTags> obj_tags;
+ map<int, transition_action> transitions;
+ map<int, transition_action> noncur_transitions;
void dump(Formatter *f) const;
};
} else {
date = lc_date->get_data();
//We need return xml error according to S3
- boost::optional<ceph::real_time> expiration_date = ceph::from_iso_8601(date);
- if (boost::none == expiration_date) {
- return false;
- }
- struct timespec expiration_time = ceph::real_clock::to_timespec(*expiration_date);
- if (expiration_time.tv_sec % (24*60*60) || expiration_time.tv_nsec) {
+ if (!check_date(date)) {
return false;
}
}
return !(single_cond && num_conditions > 1);
}
+bool LCTransition_S3::xml_end(const char* el) {
+ LCDays_S3 *lc_days = static_cast<LCDays_S3 *>(find_first("Days"));
+ LCDate_S3 *lc_date = static_cast<LCDate_S3 *>(find_first("Date"));
+ if ((lc_days && lc_date) || (!lc_days && !lc_date)) {
+ return false;
+ }
+ if (lc_days) {
+ days = lc_days->get_data();
+ } else {
+ date = lc_date->get_data();
+ //We need return xml error according to S3
+ if (!check_date(date)) {
+ return false;
+ }
+ }
+ LCStorageClass_S3 *lc_storage_class = static_cast<LCStorageClass_S3 *>(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;
+ }
+ return true;
+}
+
+bool LCNoncurTransition_S3::xml_end(const char* el) {
+ LCDays_S3 *lc_noncur_days = static_cast<LCDays_S3 *>(find_first("NoncurrentDays"));
+ if (!lc_noncur_days) {
+ return false;
+ }
+ days = lc_noncur_days->get_data();
+ LCStorageClass_S3 *lc_storage_class = static_cast<LCStorageClass_S3 *>(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;
+ }
+ return true;
+}
+
bool LCRule_S3::xml_end(const char *el) {
LCID_S3 *lc_id;
LCNoncurExpiration_S3 *lc_noncur_expiration;
LCMPExpiration_S3 *lc_mp_expiration;
LCFilter_S3 *lc_filter;
+ LCTransition_S3 *lc_transition;
+ LCNoncurTransition_S3 *lc_noncur_transition;
id.clear();
prefix.clear();
status.clear();
lc_expiration = static_cast<LCExpiration_S3 *>(find_first("Expiration"));
lc_noncur_expiration = static_cast<LCNoncurExpiration_S3 *>(find_first("NoncurrentVersionExpiration"));
lc_mp_expiration = static_cast<LCMPExpiration_S3 *>(find_first("AbortIncompleteMultipartUpload"));
- if (!lc_expiration && !lc_noncur_expiration && !lc_mp_expiration) {
+
+ XMLObjIter iter = find("Transition");
+ lc_transition = static_cast<LCTransition_S3 *>(iter.get_next());
+ XMLObjIter noncur_iter = find("NoncurrentVersionTransition");
+ lc_noncur_transition = static_cast<LCNoncurTransition_S3 *>(noncur_iter.get_next());
+
+ if (!lc_expiration && !lc_noncur_expiration && !lc_mp_expiration && !lc_transition && !lc_noncur_transition) {
return false;
} else {
if (lc_expiration) {
if (lc_mp_expiration) {
mp_expiration = *lc_mp_expiration;
}
+ while (lc_transition) {
+ if (!add_transition(lc_transition)) {
+ return false;
+ }
+ lc_transition = static_cast<LCTransition_S3 *>(iter.get_next());
+ }
+ while (lc_noncur_transition) {
+ if (!add_noncur_transition(lc_noncur_transition)) {
+ return false;
+ }
+ lc_noncur_transition = static_cast<LCNoncurTransition_S3 *>(noncur_iter.get_next());
+ }
}
-
return true;
}
LCMPExpiration_S3& mp_expir = static_cast<LCMPExpiration_S3&>(mp_expiration);
mp_expir.to_xml(out);
}
+ if (!transitions.empty()) {
+ for (auto &elem : transitions) {
+ LCTransition_S3& tran = static_cast<LCTransition_S3&>(elem.second);
+ tran.to_xml(out);
+ }
+ }
+ if (!noncur_transitions.empty()) {
+ for (auto &elem : noncur_transitions) {
+ LCNoncurTransition_S3& noncur_tran = static_cast<LCNoncurTransition_S3&>(elem.second);
+ noncur_tran.to_xml(out);
+ }
+ }
out << "</Rule>";
}
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;
}
+
+bool check_date(const string& _date)
+{
+ boost::optional<ceph::real_time> date = ceph::from_iso_8601(_date);
+ if (boost::none == date) {
+ return false;
+ }
+ struct timespec time = ceph::real_clock::to_timespec(*date);
+ if (time.tv_sec % (24*60*60) || time.tv_nsec) {
+ return false;
+ }
+ return true;
+}
}
};
+class LCStorageClass_S3 : public XMLObj
+{
+public:
+ LCStorageClass_S3() {}
+ ~LCStorageClass_S3() override {}
+ string& to_str() { return data; }
+};
+
+class LCTransition_S3 : public LCTransition, public XMLObj
+{
+public:
+ LCTransition_S3() {}
+ ~LCTransition_S3() {}
+
+ bool xml_end(const char *el) override;
+ void to_xml(ostream& out) {
+ out << "<Transition>";
+ if (!days.empty()) {
+ out << "<Days>" << days << "</Days>";
+ } else {
+ out << "<Date>" << date << "</Date>";
+ }
+ out << "<StorageClass>" << storage_class << "</StorageClass>" << "</Transition>";
+ }
+
+ 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();
+ }
+};
+
+class LCNoncurTransition_S3 : public LCTransition, public XMLObj
+{
+public:
+ LCNoncurTransition_S3() {}
+ ~LCNoncurTransition_S3() {}
+
+ bool xml_end(const char *el) override;
+ void to_xml(ostream& out) {
+ out << "<NoncurrentVersionTransition>" << "<NoncurrentDays>" << days << "</NoncurrentDays>"
+ << "<StorageClass>" << storage_class << "</StorageClass>" << "</NoncurrentVersionTransition>";
+ }
+
+ 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();
+ }
+};
+
+
class LCRule_S3 : public LCRule, public XMLObj
{
private:
const LCMPExpiration_S3& mp_expir = static_cast<const LCMPExpiration_S3&>(mp_expiration);
mp_expir.dump_xml(f);
}
-
+ if (!transitions.empty()) {
+ for (auto &elem : transitions) {
+ const LCTransition_S3& tran = static_cast<const LCTransition_S3&>(elem.second);
+ tran.dump_xml(f);
+ }
+ }
+ if (!noncur_transitions.empty()) {
+ for (auto &elem : noncur_transitions) {
+ const LCNoncurTransition_S3& noncur_tran = static_cast<const LCNoncurTransition_S3&>(elem.second);
+ noncur_tran.dump_xml(f);
+ }
+ }
f->close_section(); // Rule
}
void dump_xml(Formatter *f) const;
};
-
+bool check_date(const string& _date);
#endif