aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2012-05-08 21:31:35 +0100
committerJustin Clark-Casey (justincc)2012-05-08 21:31:35 +0100
commitabbd050a13e2b4f174c37979b46cf83f6b2f62dc (patch)
tree80cf9e103b30f58bdee41b6bd7b39449f699ca78 /OpenSim/Region/Framework
parentRevert "Better error handling if Load OAR or Save OAR fail" (diff)
downloadopensim-SC-abbd050a13e2b4f174c37979b46cf83f6b2f62dc.zip
opensim-SC-abbd050a13e2b4f174c37979b46cf83f6b2f62dc.tar.gz
opensim-SC-abbd050a13e2b4f174c37979b46cf83f6b2f62dc.tar.bz2
opensim-SC-abbd050a13e2b4f174c37979b46cf83f6b2f62dc.tar.xz
Perform SceneGraph.DuplicateObject() under existing m_updateLock already used for link and delinking, in order to avoid race conditions.
DuplicateObject() relies on source object having correct link numbers for the duration of the dupe. Both link and delink can change link numbers such that they are not consistent for short periods of time.
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs164
1 files changed, 89 insertions, 75 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 67eb0fe..4815922 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -92,8 +92,12 @@ namespace OpenSim.Region.Framework.Scenes
92 protected internal Dictionary<uint, SceneObjectGroup> SceneObjectGroupsByLocalPartID = new Dictionary<uint, SceneObjectGroup>(); 92 protected internal Dictionary<uint, SceneObjectGroup> SceneObjectGroupsByLocalPartID = new Dictionary<uint, SceneObjectGroup>();
93 93
94 /// <summary> 94 /// <summary>
95 /// Lock to prevent object group update, linking and delinking operations from running concurrently. 95 /// Lock to prevent object group update, linking, delinking and duplication operations from running concurrently.
96 /// </summary> 96 /// </summary>
97 /// <remarks>
98 /// These operations rely on the parts composition of the object. If allowed to run concurrently then race
99 /// conditions can occur.
100 /// </remarks>
97 private Object m_updateLock = new Object(); 101 private Object m_updateLock = new Object();
98 102
99 #endregion 103 #endregion
@@ -1844,96 +1848,106 @@ namespace OpenSim.Region.Framework.Scenes
1844 /// <param name="AgentID"></param> 1848 /// <param name="AgentID"></param>
1845 /// <param name="GroupID"></param> 1849 /// <param name="GroupID"></param>
1846 /// <param name="rot"></param> 1850 /// <param name="rot"></param>
1847 public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot) 1851 /// <returns>null if duplication fails, otherwise the duplicated object</returns>
1852 public SceneObjectGroup DuplicateObject(
1853 uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot)
1848 { 1854 {
1849// m_log.DebugFormat( 1855 Monitor.Enter(m_updateLock);
1850// "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", 1856
1851// originalPrimID, offset, AgentID); 1857 try
1852
1853 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
1854 if (original != null)
1855 { 1858 {
1856 if (m_parentScene.Permissions.CanDuplicateObject( 1859 // m_log.DebugFormat(
1857 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition)) 1860 // "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}",
1861 // originalPrimID, offset, AgentID);
1862
1863 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
1864 if (original == null)
1858 { 1865 {
1859 SceneObjectGroup copy = original.Copy(true); 1866 m_log.WarnFormat(
1860 copy.AbsolutePosition = copy.AbsolutePosition + offset; 1867 "[SCENEGRAPH]: Attempt to duplicate nonexistant prim id {0} by {1}", originalPrimID, AgentID);
1861 1868
1862 if (original.OwnerID != AgentID) 1869 return null;
1863 { 1870 }
1864 copy.SetOwnerId(AgentID);
1865 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID);
1866 1871
1867 SceneObjectPart[] partList = copy.Parts; 1872 if (!m_parentScene.Permissions.CanDuplicateObject(
1873 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition))
1874 return null;
1868 1875
1869 if (m_parentScene.Permissions.PropagatePermissions()) 1876 SceneObjectGroup copy = original.Copy(true);
1870 { 1877 copy.AbsolutePosition = copy.AbsolutePosition + offset;
1871 foreach (SceneObjectPart child in partList)
1872 {
1873 child.Inventory.ChangeInventoryOwner(AgentID);
1874 child.TriggerScriptChangedEvent(Changed.OWNER);
1875 child.ApplyNextOwnerPermissions();
1876 }
1877 }
1878 1878
1879 copy.RootPart.ObjectSaleType = 0; 1879 if (original.OwnerID != AgentID)
1880 copy.RootPart.SalePrice = 10; 1880 {
1881 } 1881 copy.SetOwnerId(AgentID);
1882 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID);
1882 1883
1883 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 1884 SceneObjectPart[] partList = copy.Parts;
1884 Entities.Add(copy); 1885
1885 1886 if (m_parentScene.Permissions.PropagatePermissions())
1886 lock (SceneObjectGroupsByFullID)
1887 SceneObjectGroupsByFullID[copy.UUID] = copy;
1888
1889 SceneObjectPart[] children = copy.Parts;
1890
1891 lock (SceneObjectGroupsByFullPartID)
1892 {
1893 SceneObjectGroupsByFullPartID[copy.UUID] = copy;
1894 foreach (SceneObjectPart part in children)
1895 SceneObjectGroupsByFullPartID[part.UUID] = copy;
1896 }
1897
1898 lock (SceneObjectGroupsByLocalPartID)
1899 {
1900 SceneObjectGroupsByLocalPartID[copy.LocalId] = copy;
1901 foreach (SceneObjectPart part in children)
1902 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
1903 }
1904 // PROBABLE END OF FIXME
1905
1906 // Since we copy from a source group that is in selected
1907 // state, but the copy is shown deselected in the viewer,
1908 // We need to clear the selection flag here, else that
1909 // prim never gets persisted at all. The client doesn't
1910 // think it's selected, so it will never send a deselect...
1911 copy.IsSelected = false;
1912
1913 m_numPrim += copy.Parts.Length;
1914
1915 if (rot != Quaternion.Identity)
1916 { 1887 {
1917 copy.UpdateGroupRotationR(rot); 1888 foreach (SceneObjectPart child in partList)
1889 {
1890 child.Inventory.ChangeInventoryOwner(AgentID);
1891 child.TriggerScriptChangedEvent(Changed.OWNER);
1892 child.ApplyNextOwnerPermissions();
1893 }
1918 } 1894 }
1919 1895
1920 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); 1896 copy.RootPart.ObjectSaleType = 0;
1921 copy.HasGroupChanged = true; 1897 copy.RootPart.SalePrice = 10;
1922 copy.ScheduleGroupForFullUpdate(); 1898 }
1923 copy.ResumeScripts();
1924
1925 // required for physics to update it's position
1926 copy.AbsolutePosition = copy.AbsolutePosition;
1927 1899
1928 return copy; 1900 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
1901 Entities.Add(copy);
1902
1903 lock (SceneObjectGroupsByFullID)
1904 SceneObjectGroupsByFullID[copy.UUID] = copy;
1905
1906 SceneObjectPart[] children = copy.Parts;
1907
1908 lock (SceneObjectGroupsByFullPartID)
1909 {
1910 SceneObjectGroupsByFullPartID[copy.UUID] = copy;
1911 foreach (SceneObjectPart part in children)
1912 SceneObjectGroupsByFullPartID[part.UUID] = copy;
1913 }
1914
1915 lock (SceneObjectGroupsByLocalPartID)
1916 {
1917 SceneObjectGroupsByLocalPartID[copy.LocalId] = copy;
1918 foreach (SceneObjectPart part in children)
1919 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
1920 }
1921 // PROBABLE END OF FIXME
1922
1923 // Since we copy from a source group that is in selected
1924 // state, but the copy is shown deselected in the viewer,
1925 // We need to clear the selection flag here, else that
1926 // prim never gets persisted at all. The client doesn't
1927 // think it's selected, so it will never send a deselect...
1928 copy.IsSelected = false;
1929
1930 m_numPrim += copy.Parts.Length;
1931
1932 if (rot != Quaternion.Identity)
1933 {
1934 copy.UpdateGroupRotationR(rot);
1929 } 1935 }
1936
1937 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1);
1938 copy.HasGroupChanged = true;
1939 copy.ScheduleGroupForFullUpdate();
1940 copy.ResumeScripts();
1941
1942 // required for physics to update it's position
1943 copy.AbsolutePosition = copy.AbsolutePosition;
1944
1945 return copy;
1930 } 1946 }
1931 else 1947 finally
1932 { 1948 {
1933 m_log.WarnFormat("[SCENE]: Attempted to duplicate nonexistant prim id {0}", GroupID); 1949 Monitor.Exit(m_updateLock);
1934 } 1950 }
1935
1936 return null;
1937 } 1951 }
1938 1952
1939 /// <summary> 1953 /// <summary>