using namespace librados;
-bool LCRule::valid()
+bool LCRule::valid() const
{
if (id.length() > MAX_ID_LEN) {
return false;
set_enabled(true);
}
-void RGWLifecycleConfiguration::add_rule(LCRule *rule)
+void RGWLifecycleConfiguration::add_rule(const LCRule& rule)
{
- string id;
- rule->get_id(id); // note that this will return false for groups, but that's ok, we won't search groups
- rule_map.insert(pair<string, LCRule>(id, *rule));
+ auto& id = rule.get_id(); // note that this will return false for groups, but that's ok, we won't search groups
+ rule_map.insert(pair<string, LCRule>(id, rule));
}
-bool RGWLifecycleConfiguration::_add_rule(LCRule *rule)
+bool RGWLifecycleConfiguration::_add_rule(const LCRule& rule)
{
lc_op op;
- op.status = rule->is_enabled();
- if (rule->get_expiration().has_days()) {
- op.expiration = rule->get_expiration().get_days();
+ op.status = rule.is_enabled();
+ if (rule.get_expiration().has_days()) {
+ op.expiration = rule.get_expiration().get_days();
}
- if (rule->get_expiration().has_date()) {
- op.expiration_date = ceph::from_iso_8601(rule->get_expiration().get_date());
+ if (rule.get_expiration().has_date()) {
+ op.expiration_date = ceph::from_iso_8601(rule.get_expiration().get_date());
}
- if (rule->get_noncur_expiration().has_days()) {
- op.noncur_expiration = rule->get_noncur_expiration().get_days();
+ if (rule.get_noncur_expiration().has_days()) {
+ op.noncur_expiration = rule.get_noncur_expiration().get_days();
}
- if (rule->get_mp_expiration().has_days()) {
- op.mp_expiration = rule->get_mp_expiration().get_days();
+ if (rule.get_mp_expiration().has_days()) {
+ op.mp_expiration = rule.get_mp_expiration().get_days();
}
- op.dm_expiration = rule->get_dm_expiration();
- for (const auto &elem : rule->get_transitions()) {
+ 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();
action.storage_class = elem.first;
op.transitions.emplace(elem.first, std::move(action));
}
- for (const auto &elem : rule->get_noncur_transitions()) {
+ 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());
op.noncur_transitions.emplace(elem.first, std::move(action));
}
std::string prefix;
- if (rule->get_filter().has_prefix()){
- prefix = rule->get_filter().get_prefix();
+ if (rule.get_filter().has_prefix()){
+ prefix = rule.get_filter().get_prefix();
} else {
- prefix = rule->get_prefix();
+ prefix = rule.get_prefix();
}
- if (rule->get_filter().has_tags()){
- op.obj_tags = rule->get_filter().get_tags();
+ if (rule.get_filter().has_tags()){
+ op.obj_tags = rule.get_filter().get_tags();
}
auto ret = prefix_map.emplace(std::move(prefix), std::move(op));
return ret.second;
}
-int RGWLifecycleConfiguration::check_and_add_rule(LCRule *rule)
+int RGWLifecycleConfiguration::check_and_add_rule(const LCRule& rule)
{
- if (!rule->valid()) {
+ if (!rule.valid()) {
return -EINVAL;
}
- string id;
- rule->get_id(id);
+ auto& id = rule.get_id();
if (rule_map.find(id) != rule_map.end()) { //id shouldn't be the same
return -EINVAL;
}
- rule_map.insert(pair<string, LCRule>(id, *rule));
+ rule_map.insert(pair<string, LCRule>(id, rule));
if (!_add_rule(rule)) {
return -ERR_INVALID_REQUEST;
LCRule(){};
~LCRule(){};
- bool get_id(string& _id) {
- _id = id;
- return true;
+ const string& get_id() const {
+ return id;
}
- string& get_status() {
+ const string& get_status() const {
return status;
}
- bool is_enabled() {
+ bool is_enabled() const {
return status == "Enabled";
}
status = (flag ? "Enabled" : "Disabled");
}
- string& get_prefix() {
+ const string& get_prefix() const {
return prefix;
}
- LCFilter& get_filter() {
+ const LCFilter& get_filter() const {
return filter;
}
- LCExpiration& get_expiration() {
+ const LCExpiration& get_expiration() const {
return expiration;
}
- LCExpiration& get_noncur_expiration() {
+ const LCExpiration& get_noncur_expiration() const {
return noncur_expiration;
}
- LCExpiration& get_mp_expiration() {
+ const LCExpiration& get_mp_expiration() const {
return mp_expiration;
}
- bool get_dm_expiration() {
+ bool get_dm_expiration() const {
return dm_expiration;
}
- map<string, LCTransition>& get_transitions() {
+ const map<string, LCTransition>& get_transitions() const {
return transitions;
}
- map<string, LCTransition>& get_noncur_transitions() {
+ const map<string, LCTransition>& get_noncur_transitions() const {
return noncur_transitions;
}
dm_expiration = _dm_expiration;
}
- bool add_transition(LCTransition* _transition) {
- auto ret = transitions.emplace(_transition->get_storage_class(), *_transition);
+ bool add_transition(const 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);
+ bool add_noncur_transition(const LCTransition& _noncur_transition) {
+ auto ret = noncur_transitions.emplace(_noncur_transition.get_storage_class(), _noncur_transition);
return ret.second;
}
- bool valid();
+ bool valid() const;
void encode(bufferlist& bl) const {
ENCODE_START(6, 1, bl);
CephContext *cct;
map<string, lc_op> prefix_map;
multimap<string, LCRule> rule_map;
- bool _add_rule(LCRule *rule);
+ bool _add_rule(const LCRule& rule);
bool has_same_action(const lc_op& first, const lc_op& second);
public:
explicit RGWLifecycleConfiguration(CephContext *_cct) : cct(_cct) {}
multimap<string, LCRule>::iterator iter;
for (iter = rule_map.begin(); iter != rule_map.end(); ++iter) {
LCRule& rule = iter->second;
- _add_rule(&rule);
+ _add_rule(rule);
}
DECODE_FINISH(bl);
}
void dump(Formatter *f) const;
static void generate_test_instances(list<RGWLifecycleConfiguration*>& o);
- void add_rule(LCRule* rule);
+ void add_rule(const LCRule& rule);
- int check_and_add_rule(LCRule* rule);
+ int check_and_add_rule(const LCRule& rule);
bool valid();
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)) {
+ int num = !!has_days + !!has_date + !!has_dm;
+
+ if (num != 1) {
throw RGWXMLDecoder::err("bad Expiration section");
}
//We need return xml error according to S3
throw RGWXMLDecoder::err("bad date in Date section");
}
+
+ if (has_dm) {
+ dm_expiration = (dm == "true");
+ }
}
void LCNoncurExpiration_S3::decode_xml(XMLObj *obj)
void RGWLifecycleConfiguration_S3::decode_xml(XMLObj *obj)
{
+ if (!cct) {
+ throw RGWXMLDecoder::err("ERROR: RGWLifecycleConfiguration_S3 can't be decoded without cct initialized");
+ }
vector<LCRule_S3> rules;
RGWXMLDecoder::decode_xml("Rule", rules, obj, true);
for (auto& rule : rules) {
- add_rule(&rule);
+ if (rule.get_id().empty()) {
+ string id;
+
+ // S3 generates a 48 bit random ID, maybe we could generate shorter IDs
+ static constexpr auto LC_ID_LENGTH = 48;
+
+ gen_rand_alphanumeric_lower(cct, &id, LC_ID_LENGTH);
+ rule.set_id(id);
+ }
+
+ add_rule(rule);
}
if (cct->_conf->rgw_lc_max_rules < rule_map.size()) {
status.clear();
dm_expiration = false;
- // S3 generates a 48 bit random ID, maybe we could generate shorter IDs
- static constexpr auto LC_ID_LENGTH = 48;
-
- if (!RGWXMLDecoder::decode_xml("ID", id, obj)) {
- gen_rand_alphanumeric_lower(cct, &id, LC_ID_LENGTH);
- }
+ RGWXMLDecoder::decode_xml("ID", id, obj);
LCFilter_S3 filter_s3;
if (!RGWXMLDecoder::decode_xml("Filter", filter_s3, obj)) {
throw RGWXMLDecoder::err("bad Status in Filter");
}
-
LCExpiration_S3 s3_expiration;
- LCExpiration_S3 s3_noncur_expiration;
- LCExpiration_S3 s3_mp_expiration;
+ LCNoncurExpiration_S3 s3_noncur_expiration;
+ LCMPExpiration_S3 s3_mp_expiration;
LCFilter_S3 s3_filter;
bool has_expiration = RGWXMLDecoder::decode_xml("Expiration", s3_expiration, obj);
mp_expiration = s3_mp_expiration;
}
for (auto& t : transitions) {
- if (!add_transition(&t)) {
+ if (!add_transition(t)) {
throw RGWXMLDecoder::err("Failed to add transition");
}
}
for (auto& t : noncur_transitions) {
- if (!add_noncur_transition(&t)) {
+ if (!add_noncur_transition(t)) {
throw RGWXMLDecoder::err("Failed to add non-current version transition");
}
}
multimap<string, LCRule>::iterator iter;
for (iter = rule_map.begin(); iter != rule_map.end(); ++iter) {
LCRule& src_rule = iter->second;
- ret = dest.check_and_add_rule(&src_rule);
+ ret = dest.check_and_add_rule(src_rule);
if (ret < 0)
return ret;
}
class LCRule_S3 : public LCRule
{
-private:
- CephContext *cct;
public:
- LCRule_S3(): cct(nullptr) {}
- explicit LCRule_S3(CephContext *_cct): cct(_cct) {}
+ LCRule_S3() {}
void dump_xml(Formatter *f) const;
void decode_xml(XMLObj *obj);
-
- void set_ctx(CephContext *ctx) {
- cct = ctx;
- }
};
class RGWLifecycleConfiguration_S3 : public RGWLifecycleConfiguration
{
bufferlist bl;
- RGWLifecycleConfiguration_S3 config;
+ RGWLifecycleConfiguration_S3 config(s->cct);
RGWXMLParser parser;
RGWLifecycleConfiguration_S3 new_config(s->cct);
RGWXMLDecoder::decode_xml("LifecycleConfiguration", config, &parser);
} catch (RGWXMLDecoder::err& err) {
ldpp_dout(this, 5) << "Bad lifecycle configuration: " << err << dendl;
- op_ret = -EINVAL;
+ op_ret = -ERR_MALFORMED_XML;
return;
}
if (op_ret < 0)
return;
- config.dump_xml(s->formatter);
+ encode_xml("LifecycleConfiguration", XMLNS_AWS_S3, config, s->formatter);
rgw_flush_formatter_and_reset(s, s->formatter);
}
if (!field)
return 0;
- string& s = field->get_data();
+ auto& s = field->get_data();
if (stringcasecmp(s, "Requester") == 0) {
*requester_pays = true;
class RGWGetLC_ObjStore_S3 : public RGWGetLC_ObjStore {
protected:
- RGWLifecycleConfiguration_S3 config;
+ RGWLifecycleConfiguration_S3 config;
public:
RGWGetLC_ObjStore_S3() {}
~RGWGetLC_ObjStore_S3() override {}
return obj;
}
+bool XMLObjIter::get_name(string *name) const
+{
+ if (cur == end) {
+ return false;
+ }
+
+ *name = cur->first;
+ return true;
+}
+
ostream& operator<<(ostream &out, const XMLObj &obj) {
out << obj.obj_type << ": " << obj.data;
return out;
data.append(s, len);
}
-string& XMLObj::
+const string& XMLObj::
XMLObj::get_data()
{
return data;
}
+const string& XMLObj::
+XMLObj::get_obj_type()
+{
+ return obj_type;
+}
+
XMLObj *XMLObj::
XMLObj::get_parent()
{
map<string, XMLObj *>::iterator first;
map<string, XMLObj *>::iterator last;
first = children.begin();
- if (first != children.end()) {
- last = children.upper_bound(first->first);
- }else
- last = children.end();
+ last = children.end();
iter.set(first, last);
return iter;
}
void decode_xml_obj(unsigned long& val, XMLObj *obj)
{
- string& s = obj->get_data();
+ auto& s = obj->get_data();
const char *start = s.c_str();
char *p;
~XMLObjIter();
void set(const XMLObjIter::map_iter_t &_cur, const XMLObjIter::map_iter_t &_end);
XMLObj *get_next();
+ bool get_name(string *name) const;
};
/**
bool xml_start(XMLObj *parent, const char *el, const char **attr);
virtual bool xml_end(const char *el);
virtual void xml_handle_data(const char *s, int len);
- string& get_data();
+ const string& get_data();
+ const string& get_obj_type();
XMLObj *get_parent();
void add_child(string el, XMLObj *obj);
bool get_attr(string name, string& attr);
template<class T>
static bool decode_xml(const char *name, T& val, XMLObj *obj, bool mandatory = false);
+ template<class T>
+ static bool decode_xml(const char *name, std::vector<T>& v, XMLObj *obj, bool mandatory = false);
+
template<class C>
static bool decode_xml(const char *name, C& container, void (*cb)(C&, XMLObj *obj), XMLObj *obj, bool mandatory = false);
}
}
-template<class T>
-void decode_xml_obj(std::vector<T>& v, XMLObj *obj)
-{
- v.clear();
-
- XMLObjIter iter = obj->find_first();
- XMLObj *o;
-
- while ((o = iter.get_next())) {
- T val;
- decode_xml_obj(val, o);
- v.push_back(val);
- }
-}
-
template<class T>
bool RGWXMLDecoder::decode_xml(const char *name, T& val, XMLObj *obj, bool mandatory)
{
return true;
}
+template<class T>
+bool RGWXMLDecoder::decode_xml(const char *name, std::vector<T>& v, XMLObj *obj, bool mandatory)
+{
+ XMLObjIter iter = obj->find(name);
+ XMLObj *o = iter.get_next();
+
+ v.clear();
+
+ if (!o) {
+ if (mandatory) {
+ string s = "missing mandatory field " + string(name);
+ throw err(s);
+ }
+ return false;
+ }
+
+ do {
+ T val;
+ try {
+ decode_xml_obj(val, o);
+ } catch (err& e) {
+ string s = string(name) + ": ";
+ s.append(e.message);
+ throw err(s);
+ }
+ v.push_back(val);
+ } while ((o = iter.get_next()));
+ return true;
+}
+
template<class C>
bool RGWXMLDecoder::decode_xml(const char *name, C& container, void (*cb)(C&, XMLObj *), XMLObj *obj, bool mandatory)
{
f->close_section();
}
+template<class T>
+static void encode_xml(const char *name, const char *ns, const T& val, ceph::Formatter *f)
+{
+ f->open_object_section_in_ns(name, ns);
+ val.dump_xml(f);
+ f->close_section();
+}
+
void encode_xml(const char *name, const string& val, ceph::Formatter *f);
void encode_xml(const char *name, const char *val, ceph::Formatter *f);
void encode_xml(const char *name, bool val, ceph::Formatter *f);