]> git.ipfire.org Git - thirdparty/snapper.git/commitdiff
- split XAttributes class into XAttributes and XAModification. This commit is partial...
authorOndrej Kozina <okozina@redhat.com>
Wed, 23 Jan 2013 17:06:03 +0000 (18:06 +0100)
committerOndrej Kozina <okozina@redhat.com>
Wed, 27 Feb 2013 16:24:57 +0000 (17:24 +0100)
snapper/File.cc
snapper/XAttributes.cc
snapper/XAttributes.h

index ef5edc46d8785d7f65afc98308b252bf291e440f..ccb03a0feced4892a65e1fd9b96f775e7b094689 100644 (file)
@@ -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;
index 5cca5cc1c57b6b7d309993dd838005fdb2321c6e..061b307ec4f064052dca4bf442fc1f284f45a285 100644 (file)
 #include "snapper/Exception.h"
 #include "snapper/Log.h"
 
+#include <boost/scoped_array.hpp>
+#include <boost/scoped_ptr.hpp>
+
 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<char> 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<uint8_t> 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<xa_map_citer, bool> 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<xa_map_t> 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
index 59fc67ced33ca3868b24a49035de6667ccde4f33..05b15268a4bc4d6f77be9f81854368f91c889b9e 100644 (file)
@@ -36,10 +36,12 @@ namespace snapper
        using std::ostream;
        using std::vector;
 
+        class XAModification;
+        class XAttributes;
+
        typedef vector<uint8_t> xa_value_t;
        typedef map<string, xa_value_t> xa_map_t;
        typedef pair<string, xa_value_t> xa_pair_t;
-        typedef pair<uint8_t, string> xa_cmp_pair_t;
         typedef pair<bool, xa_value_t> xa_find_pair_t;
         typedef vector<string> xa_name_vec_t;
 
@@ -58,38 +60,53 @@ namespace snapper
         // create - whole new XA
         // delete - remove XA
         // replace - change in xa_value
-        typedef map<uint8_t, xa_name_vec_t> xa_change_t;
+        typedef map<uint8_t, xa_name_vec_t> 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