From: Ondrej Kozina Date: Wed, 23 Jan 2013 17:06:03 +0000 (+0100) Subject: - split XAttributes class into XAttributes and XAModification. This commit is partial... X-Git-Tag: v0.1.3~18^2~45 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=a032ceda81eb8ff14c494ab09d6da9b4add8db39;p=thirdparty%2Fsnapper.git - split XAttributes class into XAttributes and XAModification. This commit is partial rewrite --- diff --git a/snapper/File.cc b/snapper/File.cc index ef5edc46..ccb03a0f 100644 --- a/snapper/File.cc +++ b/snapper/File.cc @@ -552,10 +552,13 @@ namespace snapper XAttributes xa_src(src_fd), xa_dest(dest_fd); y2deb("xa_src object: " << xa_src << std::endl << "xa_dest object: " << xa_dest); - xa_dest.generateXaComparison(xa_src); - y2deb("xa_dest object after generateXaComparison(): " << xa_dest); - ret_val = xa_dest.serializeTo(dest_fd); - y2deb("xa_dest object after serializeTo(): " << xa_dest); + // xa_dest gets modified in case xa_modmap + // construction is successfull + XAModification xa_mod(xa_src, xa_dest); + y2deb("xa_dest object after XAModification(): " << xa_dest); + y2deb("xa_modmap(xa_dest) object: " << xa_mod); + + ret_val = xa_dest.serializeModificationsTo(dest_fd, xa_mod); } catch (IOErrorException ioe) { ret_val = false; diff --git a/snapper/XAttributes.cc b/snapper/XAttributes.cc index 5cca5cc1..061b307e 100644 --- a/snapper/XAttributes.cc +++ b/snapper/XAttributes.cc @@ -32,14 +32,11 @@ #include "snapper/Exception.h" #include "snapper/Log.h" +#include +#include + namespace snapper { - XAttributes::XAttributes() - { - xamap = new xa_map_t; - xachmap = NULL; - } - XAttributes::XAttributes(int fd) { y2deb("entering Xattributes(int fd) constructor"); @@ -51,258 +48,160 @@ namespace snapper } // +1 to cover size == 0 - char *names = new char[size + 1]; + boost::scoped_array names(new char[size + 1]); names[size] = '\0'; y2deb("XAttributes names-list size is: " << size); - size = flistxattr(fd, names, size); + size = flistxattr(fd, names.get(), size); if (size < 0) { y2err("Couldn't get xattributes names-list: " << stringerror(errno)); throw IOErrorException(); } - - xamap = new xa_map_t; int pos = 0; while (pos < size) { - string name = string(names + pos); + string name = string(names.get() + pos); // move beyond separating '\0' char pos += name.length() + 1; ssize_t v_size = fgetxattr(fd, name.c_str(), NULL, 0); if (v_size < 0) { - y2err("Couldn't get a xattribute value size for the xattribute name '" << name << "': " << stringerror(errno)); + y2err("Couldn't get a xattribute value size for the xattribute name '" << name << "': " << stringerror(errno)); throw IOErrorException(); } y2deb("XAttribute value size for xattribute name: '" << name << "' is " << v_size); - uint8_t *buffer = new uint8_t[v_size]; + boost::scoped_array buffer(v_size ? new uint8_t[v_size] : NULL); - v_size = fgetxattr(fd, name.c_str(), (void *)buffer, v_size); + v_size = fgetxattr(fd, name.c_str(), (void *)buffer.get(), v_size); if (v_size < 0) { y2err("Coudln't get xattrbitue value for the xattrbite name '" << name << "': "); throw IOErrorException(); } - xa_value_t xa_value(buffer, buffer + v_size); - - xamap->insert(xa_pair_t(name, xa_value)); - - delete[] buffer; + if (!xamap.insert(xa_pair_t(name, xa_value_t(buffer.get(), buffer.get() + v_size))).second) + { + y2err("Duplicite extended attribute name in source file!"); + // TODO: possible XAException candidate + throw IOErrorException(); + } } - - delete[] names; - - xachmap = NULL; } XAttributes::XAttributes(const XAttributes &xa) { y2deb("Starting copy constructor XAttribute(const XAttribute&)"); - xamap = new xa_map_t(*(xa.xamap)); - - if (xa.xachmap) - xachmap = new xa_change_t(*(xa.xachmap)); + xamap = xa.xamap; } - XAttributes::~XAttributes() - { - delete xamap; - delete xachmap; - } - xa_find_pair_t XAttributes::find(const string &xa_name) const { - xa_map_citer cit = xamap->find(xa_name); - if (cit != xamap->end()) + xa_map_citer cit = xamap.find(xa_name); + if (cit != xamap.end()) { return xa_find_pair_t(true, cit->second); } return xa_find_pair_t(false, xa_value_t()); } - - void - XAttributes::insert(const xa_pair_t &p) - { - pair ret = xamap->insert(p); - if (!ret.second) - y2war("Couldn't insert pair xa_name==" << p.first << ":xa_value==" << p.second); - - } - - void - XAttributes::generateXaComparison(const XAttributes &src_xa) - { - xa_change_t *change_map = new xa_change_t(); - (*change_map)[XA_DELETE] = xa_name_vec_t(); - (*change_map)[XA_REPLACE] = xa_name_vec_t(); - (*change_map)[XA_CREATE] = xa_name_vec_t(); - - delete this->xachmap; - - if (*this == src_xa) - { - this->xachmap = change_map; - - return; - } - - xa_map_citer src_cit = src_xa.xamap->begin(); - xa_map_iter it = this->xamap->begin(); - - while (src_cit != src_xa.xamap->end() && it != this->xamap->end()) - { - if (src_cit->first == it->first) - { - if (src_cit->second != it->second) - { - (*change_map)[XA_REPLACE].push_back(src_cit->first); - (*this->xamap)[src_cit->first] = src_cit->second; - } - src_cit++; - it++; - } - else if (src_cit->first < it->first) - { - (*change_map)[XA_CREATE].push_back(src_cit->first); - it = this->xamap->insert(xa_pair_t(src_cit->first, src_cit->second)).first; - - src_cit++; - } - else - { - (*change_map)[XA_DELETE].push_back(it->first); - xa_map_iter tmp = it++; - this->xamap->erase(tmp); - } - } - - while (src_cit != src_xa.xamap->end()) - { - (*change_map)[XA_CREATE].push_back(src_cit->first); - it = this->xamap->insert(xa_pair_t(src_cit->first, src_cit->second)).first; - - src_cit++; - } - - while (it != this->xamap->end()) - { - (*change_map)[XA_DELETE].push_back(it->first); - xa_map_iter tmp = it++; - it = this->xamap->erase(tmp); - } - - this->xachmap = change_map; - } bool - XAttributes::serializeTo(int dest_fd) + XAttributes::serializeModificationsTo(int dest_fd, const XAModification &xa_mods) const { - if (!this->xachmap) + if (this != xa_mods.getDestination()) { - y2war("Missing change map!"); return false; + // TODO: throw exception: invalid request } - xa_change_citer cit = this->xachmap->begin(); - - while(cit != this->xachmap->end()) + for (xa_mod_citer cit = xa_mods.cbegin(); cit != xa_mods.cend(); cit++) { - xa_name_vec_citer name_cit = cit->second.begin(); - - switch (cit->first) + for (xa_name_vec_citer name_cit = cit->second.begin(); name_cit != cit->second.end(); name_cit++) { - case XA_DELETE: - while (name_cit != cit->second.end()) - { + switch (cit->first) + { + case XA_DELETE: y2deb("delete xattribute: " << *name_cit); if (fremovexattr(dest_fd, (*name_cit).c_str())) { y2err("Couldn't remove xattribute '" << *name_cit << "': " << stringerror(errno)); return false; } - name_cit++; - } - break; + break; - case XA_REPLACE: - while (name_cit != cit->second.end()) - { + case XA_REPLACE: y2deb("replace xattribute: " << *name_cit); - xa_find_pair_t fnd = find(*name_cit); - if (!fnd.first) { - y2err("Internal error: Couldn't find xattribute '" << *name_cit << "'"); - return false; - } - if (fnd.second.empty()) - { - y2deb("new value for xattribute '" << *name_cit << "' is empty!"); - if (fsetxattr(dest_fd, (*name_cit).c_str(), NULL, 0, XATTR_REPLACE)) + xa_find_pair_t fnd = find(*name_cit); + if (!fnd.first) { - y2err("Couldn't replace xattribute '" << *name_cit << "' by new (empty) value: " << stringerror(errno)); + y2err("Internal error: Couldn't find xattribute '" << *name_cit << "'"); return false; } - } - else - { - y2deb("new value: '" << fnd.second << "'"); - if (fsetxattr(dest_fd, (*name_cit).c_str(), &fnd.second.front(), fnd.second.size(), XATTR_REPLACE)) + if (fnd.second.empty()) { - y2err("Couldn't replace xattribute by new value: " << stringerror(errno)); - return false; + y2deb("new value for xattribute '" << *name_cit << "' is empty!"); + if (fsetxattr(dest_fd, (*name_cit).c_str(), NULL, 0, XATTR_REPLACE)) + { + y2err("Couldn't replace xattribute '" << *name_cit << "' by new (empty) value: " << stringerror(errno)); + return false; + } + } + else + { + y2deb("new value: '" << fnd.second << "'"); + if (fsetxattr(dest_fd, (*name_cit).c_str(), &fnd.second.front(), fnd.second.size(), XATTR_REPLACE)) + { + y2err("Couldn't replace xattribute by new value: " << stringerror(errno)); + return false; + } } } - name_cit++; - } - break; + break; - case XA_CREATE: - while (name_cit != cit->second.end()) - { + case XA_CREATE: y2deb("create xattribute: " << *name_cit); - xa_find_pair_t fnd = find(*name_cit); - if (!fnd.first) { - y2err("Internal error: Couldn't find xattribute '" << *name_cit << "'"); - return false; - } - if (fnd.second.empty()) - { - y2deb("new value for xattribute '" << *name_cit << "' is empty!"); - if (fsetxattr(dest_fd, (*name_cit).c_str(), NULL, 0, XATTR_CREATE)) + xa_find_pair_t fnd = find(*name_cit); + if (!fnd.first) { - y2err("Couldn't create xattribute '" << *name_cit << "' by new (empty) value: " << stringerror(errno)); + y2err("Internal error: Couldn't find xattribute '" << *name_cit << "'"); return false; } - } - else - { - y2deb("new value: '" << fnd.second << "'"); - if (fsetxattr(dest_fd, (*name_cit).c_str(), &fnd.second.front(), fnd.second.size(), XATTR_CREATE)) + if (fnd.second.empty()) { - y2err("Couldn't create xattribute '" << *name_cit << "': " << stringerror(errno)); - return false; + y2deb("new value for xattribute '" << *name_cit << "' is empty!"); + if (fsetxattr(dest_fd, (*name_cit).c_str(), NULL, 0, XATTR_CREATE)) + { + y2err("Couldn't create xattribute '" << *name_cit << "' by new (empty) value: " << stringerror(errno)); + return false; + } + } + else + { + y2deb("new value: '" << fnd.second << "'"); + if (fsetxattr(dest_fd, (*name_cit).c_str(), &fnd.second.front(), fnd.second.size(), XATTR_CREATE)) + { + y2err("Couldn't create xattribute '" << *name_cit << "': " << stringerror(errno)); + return false; + } } } - name_cit++; - } - break; + break; - default: - y2err("Internal Error in XAttributes()"); - return false; + default: + y2err("Internal Error in XAttributes()"); + return false; + } } - cit++; } return true; } @@ -313,16 +212,7 @@ namespace snapper y2deb("Entering XAttribute::operator=()"); if (this != &xa) { - delete this->xamap; - this->xamap = new xa_map_t(*(xa.xamap)); - - delete this->xachmap; - this->xachmap = NULL; - - if (xa.xachmap) - { - this->xachmap = new xa_change_t(*(xa.xachmap)); - } + this->xamap = xa.xamap; } return *this; @@ -332,28 +222,19 @@ namespace snapper XAttributes::operator==(const XAttributes& xa) const { y2deb("Entering XAttribute::operator==()"); - // do not care about change map. the content is xamap only - return (this == &xa) ? true : (*(this->xamap) == *(xa.xamap)); + return (this == &xa) ? true : (this->xamap == xa.xamap); } ostream& operator<<(ostream &out, const XAttributes &xa) { - xa_map_citer it = xa.xamap->begin(); + xa_map_citer cit = xa.cbegin(); - if (it == xa.xamap->end()) + if (cit == xa.cend()) out << "(XA container is empty)"; - while (it != xa.xamap->end()) - { - out << "xa_name: " << it->first << ", xa_value: " << it->second << std::endl; - it++; - } - - if (xa.xachmap) - { - out << "change content: " << std::endl << *xa.xachmap; - } + for (; cit != xa.cend(); cit++) + out << "xa_name: " << cit->first << ", xa_value: " << cit->second << std::endl; return out; } @@ -373,33 +254,129 @@ namespace snapper } ostream& - operator<<(ostream &out, const xa_change_t &xa_change) + operator<<(ostream &out, const xa_modification_t &xa_change) { - xa_change_citer cit = xa_change.begin(); - - while (cit != xa_change.end()) + if (xa_change.find(XA_DELETE)->second.empty() && + xa_change.find(XA_REPLACE)->second.empty() && + xa_change.find(XA_CREATE)->second.empty() + ) + out << "(xa_modification_t is empty)"; + else { - xa_name_vec_citer name_cit = cit->second.begin(); - switch (cit->first) + for (xa_mod_citer cit = xa_change.begin(); cit != xa_change.end(); cit++) { - case XA_DELETE: - out << "XA_DELETE"; - break; - case XA_REPLACE: - out << "XA_REPLACE"; - break; - case XA_CREATE: - out << "XA_CREATE"; - break; - default: - out << "unknown"; + switch (cit->first) + { + case XA_DELETE: + out << "XA_DELETE:"; + break; + case XA_REPLACE: + out << "XA_REPLACE:"; + break; + case XA_CREATE: + out << "XA_CREATE:"; + break; + default: + out << "(!!!unknown!!!)"; + } + for (xa_name_vec_citer name_cit = cit->second.begin(); name_cit != cit->second.end(); name_cit++) + out << *name_cit << ',' << std::endl; } - out << " mark:" << std::endl; - while (name_cit != cit->second.end()) - out << *name_cit++ << std::endl; - cit++; } return out; } + + XAModification::XAModification() + { + xamodmap[XA_DELETE] = xa_name_vec_t(); + xamodmap[XA_REPLACE] = xa_name_vec_t(); + xamodmap[XA_CREATE] = xa_name_vec_t(); + + p_xa_dest = NULL; + } + + XAModification::XAModification(const XAttributes &src_xa, XAttributes &dest_xa) + { + xamodmap[XA_DELETE] = xa_name_vec_t(); + xamodmap[XA_REPLACE] = xa_name_vec_t(); + xamodmap[XA_CREATE] = xa_name_vec_t(); + + xa_map_citer src_cit = src_xa.xamap.begin(); + + boost::scoped_ptr p_xamap(new xa_map_t(dest_xa.xamap)); + + xa_map_iter it = p_xamap->begin(); + + while (src_cit != src_xa.xamap.end() && it != p_xamap->end()) + { + y2deb("this src_xa_name: " << src_cit->first); + y2deb("this dest_xa_name: " << it->first); + + if (src_cit->first == it->first) + { + y2deb("names matched"); + if (src_cit->second != it->second) + { + y2deb("create XA_REPLACE event"); + xamodmap[XA_REPLACE].push_back(src_cit->first); + (*p_xamap)[it->first] = src_cit->second; + } + src_cit++; + it++; + } + else if (src_cit->first < it->first) + { + y2deb("src name < dest name"); + xamodmap[XA_CREATE].push_back(src_cit->first); + it = p_xamap->insert(xa_pair_t(src_cit->first, src_cit->second)).first; + if (it != p_xamap->end()) + y2deb("next dest name is " << it->first); + + src_cit++; + } + else + { + y2deb("src name > dest name"); + xamodmap[XA_DELETE].push_back(it->first); + xa_map_iter tmp = it++; + p_xamap->erase(tmp); + if (it != p_xamap->end()) + y2deb("next dest name is " << it->first); + } + } + + if (it != p_xamap->end()) + { + xa_map_iter tmp = it; + while (tmp != p_xamap->end()) + { + xamodmap[XA_DELETE].push_back(tmp->first); + tmp++; + } + p_xamap->erase(it, p_xamap->end()); + } + + while (src_cit != src_xa.xamap.end()) + { + xamodmap[XA_CREATE].push_back(src_cit->first); + if (!p_xamap->insert(xa_pair_t(src_cit->first, src_cit->second)).second) + { + // TODO: throw XA error + y2war("Internal error: XA w/ name: '" << src_cit->first << "' already exists"); + } + + src_cit++; + } + + // TODO: how to do atomic change in a sane way? + dest_xa.xamap = *p_xamap; + this->p_xa_dest = &dest_xa; + } + + ostream& + operator<<(ostream &out, const XAModification &xa_mod) + { + return out << xa_mod; + } } \ No newline at end of file diff --git a/snapper/XAttributes.h b/snapper/XAttributes.h index 59fc67ce..05b15268 100644 --- a/snapper/XAttributes.h +++ b/snapper/XAttributes.h @@ -36,10 +36,12 @@ namespace snapper using std::ostream; using std::vector; + class XAModification; + class XAttributes; + typedef vector xa_value_t; typedef map xa_map_t; typedef pair xa_pair_t; - typedef pair xa_cmp_pair_t; typedef pair xa_find_pair_t; typedef vector xa_name_vec_t; @@ -58,38 +60,53 @@ namespace snapper // create - whole new XA // delete - remove XA // replace - change in xa_value - typedef map xa_change_t; + typedef map xa_modification_t; // iterators typedef xa_map_t::iterator xa_map_iter; typedef xa_map_t::const_iterator xa_map_citer; - typedef xa_change_t::const_iterator xa_change_citer; + typedef xa_modification_t::const_iterator xa_mod_citer; typedef xa_name_vec_t::const_iterator xa_name_vec_citer; class XAttributes { private: - xa_map_t *xamap; - xa_change_t *xachmap; - public: - XAttributes(); - XAttributes(int); - XAttributes(const XAttributes&); - ~XAttributes(); - - xa_find_pair_t find(const string&) const; - void insert(const xa_pair_t&); - void generateXaComparison(const XAttributes&); - bool serializeTo(int); - - XAttributes& operator=(const XAttributes&); - bool operator==(const XAttributes&) const; - - friend ostream& operator<<(ostream&, const XAttributes&); + xa_map_t xamap; + public: + XAttributes(int); + XAttributes(const XAttributes&); + + xa_map_citer cbegin() const { return xamap.begin(); } + xa_map_citer cend() const { return xamap.end(); } + xa_find_pair_t find(const string&) const; + // this method is not const! (it changes xamap to reflect new state)! + bool serializeModificationsTo(int, const XAModification&) const; + + XAttributes& operator=(const XAttributes&); + bool operator==(const XAttributes&) const; + + // XAModification is able to atomically modify xamap atribute + friend class XAModification; }; + class XAModification + { + private: + xa_modification_t xamodmap; + const XAttributes *p_xa_dest; + public: + XAModification(); + XAModification(const XAttributes&, XAttributes&); + + xa_mod_citer cbegin() const { return xamodmap.begin(); }; + xa_mod_citer cend() const { return xamodmap.end(); }; + const XAttributes* getDestination() const { return p_xa_dest; } + }; + + ostream& operator<<(ostream&, const XAModification&); + ostream& operator<<(ostream&, const XAttributes&); ostream& operator<<(ostream&, const xa_value_t&); - ostream& operator<<(ostream&, const xa_change_t&); + ostream& operator<<(ostream&, const xa_modification_t&); } #endif