Hello Michael,

On 07/13/2011 05:43 AM, Michael Raab wrote:
some days ago I thought it would be a good idea to call 
Changelist::compactChanged() on our current changelist after loading a huge 
chunk of data to assure to transmit as less data as possible to our render 
servers.
Today I observed some weired synchronization problems. After some debugging it 
seems that those were caused by the compactChanged() function call.
I don't know what the original intention of this function was, but it seems to 
lose very relevant information. For example all information about destroyed 
fieldcontainers disappear after compact().

hmm, looking at the function there are indeed a few problems with it. It seems to be written with the implicit assumption that the complete change history is contained in the CL that is being compacted:
1) it drops add/subrefs for containers that don't have create entry
2) it drops destroys for containers that don't have a create entry [1]
3) it looses all changed records and replaces them with ones that mark all fields changed for created containers (i.e. entries for containers that are only changed are lost). The attached patch is an attempt to remove this implicit assumption, but it does not fix 3) above (I just noticed it while writing this mail).

        Cheers,
                Carsten

[1] under the assumption of complete history it is ok to end up with no destroy records if the corresponding create record is deleted (which is what used to happen).
Index: Source/System/FieldContainer/OSGChangeList.cpp
===================================================================
RCS file: 
/cvsroot/opensg/OpenSG/Source/System/FieldContainer/OSGChangeList.cpp,v
retrieving revision 1.14
diff -u -r1.14 OSGChangeList.cpp
--- Source/System/FieldContainer/OSGChangeList.cpp      13 Jan 2010 15:19:58 
-0000      1.14
+++ Source/System/FieldContainer/OSGChangeList.cpp      13 Jul 2011 18:48:57 
-0000
@@ -355,59 +355,136 @@
     return _max_changed_size;
 }
 
+namespace
+{
+    struct CLInfo
+    {
+        explicit CLInfo(Int32 dRC = 0, bool c = false, bool d = false) :
+            deltaRC(dRC),
+            create (c  ),
+            destroy(d  )
+        {
+        }
+
+        Int32 deltaRC;
+        bool  create;
+        bool  destroy;
+    };
+}
+
 void ChangeList::compactChanged(void)
 {
-    std::map<UInt32, UInt32> clStore;
+    typedef std::map<UInt32, CLInfo> CLMap;
+
+    CLMap clMap;
 
     // created
     for(ChangeList::idrefd_const_iterator i = beginCreated(); i != 
endCreated(); ++i)
     {
-        std::map<UInt32, UInt32>::iterator ci = clStore.find(*i);
-        if(ci == clStore.end())
-            clStore.insert(std::pair<UInt32, UInt32>(*i, 0));
+        CLMap::iterator ci = clMap.find(*i);
+        if(ci == clMap.end())
+            clMap.insert(CLMap::value_type(*i, CLInfo(0, true)));
     }
 
     // addRef
     for(ChangeList::idrefd_const_iterator i = beginAddRefd(); i != 
endAddRefd(); ++i)
     {
-        std::map<UInt32, UInt32>::iterator ci = clStore.find(*i);
-        if(ci != clStore.end())
-            (*ci).second++;
-        //else
-        //    FWARNING(("Called addRef on a not created fieldcontainer!\n"));
+        CLMap::iterator ci = clMap.find(*i);
+        if(ci != clMap.end())
+        {
+            (*ci).second.deltaRC += 1;
+        }
+        else
+        {
+            clMap.insert(CLMap::value_type(*i, CLInfo(1)));
+        }
     }
 
     // subRef
     for(ChangeList::idrefd_const_iterator i = beginSubRefd(); i != 
endSubRefd(); ++i)
     {
-        std::map<UInt32, UInt32>::iterator ci = clStore.find(*i);
-        if(ci != clStore.end())
-            (*ci).second--;
-        //else
-        //    FWARNING(("Called subRef on a not created fieldcontainer!\n"));
+        CLMap::iterator ci = clMap.find(*i);
+        if(ci != clMap.end())
+        {
+            (*ci).second.deltaRC -+ 1;
+        }
+        else
+        {
+            clMap.insert(CLMap::value_type(*i, CLInfo(-1)));
+        }
+
     }
 
     // destroyed
     for(ChangeList::idrefd_const_iterator i = beginDestroyed(); i != 
endDestroyed(); ++i)
     {
-        std::map<UInt32, UInt32>::iterator ci = clStore.find(*i);
-        if(ci != clStore.end())
-            clStore.erase(ci);
+        CLMap::iterator ci = clMap.find(*i);
+        if(ci != clMap.end())
+        {
+            if((*ci).second.create == true)
+            {
+                clMap.erase(ci);
+            }
+            else
+            {
+                clMap.insert(CLMap::value_type(*i, CLInfo(0, false, true)));
+            }
+        }
+        else
+        {
+            clMap.insert(CLMap::value_type(*i, CLInfo(0, false, true)));
+        }
     }
 
     clearAll();
 
-    for(std::map<UInt32, UInt32>::iterator i = clStore.begin();i != 
clStore.end(); ++i)
+    for(CLMap::iterator i = clMap.begin(); i != clMap.end(); ++i)
     {
-        UInt32 id = (*i).first;
+        UInt32            id = (*i).first;
         FieldContainerPtr fc = FieldContainerFactory::the()->getContainer(id);
+
         if(fc != NullFC)
         {
-            addCreated(id);
-            for(UInt32 j=0;j<(*i).second;++j)
-                addAddRefd(fc);
+            if((*i).second.create == true)
+            {
+                addCreated(id);
+            }
+
+            if((*i).second.deltaRC > 0)
+            {
+                for(Int32 j = 0; j < (*i).second.deltaRC; ++j)
+                    addAddRefd(fc);
+            }
+            else if((*i).second.deltaRC < 0)
+            {
+                for(Int32 j = 0; j > (*i).second.deltaRC; --j)
+                    addSubRefd(fc);
+            }
+
+            if((*i).second.destroy == true)
+            {
+                FWARNING(("ChangeList::compactChanged: "
+                          "FC for id [%u] is NOT NulLFC, but CL contains "
+                          "destoy entry.\n", id));
+
+                addDestroyed(id);
+            }
+
             addChanged(fc, FieldBits::AllFields);
         }
+        else
+        {
+            if((*i).second.destroy == true)
+            {
+                addDestroyed(id);
+            }
+            else
+            {
+                FWARNING(("ChangeList::compactChanged: "
+                          "FC for id [%u] is NulLFC, but CL contains "
+                          "no destoy entry.\n", id));
+            }
+        }
     }
 }
 
------------------------------------------------------------------------------
AppSumo Presents a FREE Video for the SourceForge Community by Eric 
Ries, the creator of the Lean Startup Methodology on "Lean Startup 
Secrets Revealed." This video shows you how to validate your ideas, 
optimize your ideas and identify your business strategy.
http://p.sf.net/sfu/appsumosfdev2dev
_______________________________________________
Opensg-users mailing list
Opensg-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensg-users

Reply via email to