aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorMelanie2009-12-06 00:25:04 +0000
committerMelanie2009-12-06 02:53:42 +0000
commit46d5add175b2c4281780c839283616fbe5394b67 (patch)
treec548ae5b3297736e8a87a55967a5c117c1855d9f /OpenSim/Region
parentEliminate multiple updates on link/unlink (diff)
downloadopensim-SC_OLD-46d5add175b2c4281780c839283616fbe5394b67.zip
opensim-SC_OLD-46d5add175b2c4281780c839283616fbe5394b67.tar.gz
opensim-SC_OLD-46d5add175b2c4281780c839283616fbe5394b67.tar.bz2
opensim-SC_OLD-46d5add175b2c4281780c839283616fbe5394b67.tar.xz
Lock updates out while linking and unlinking
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs255
1 files changed, 134 insertions, 121 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index d87e814..5efe188 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Threading;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using System.Reflection; 31using System.Reflection;
31using OpenMetaverse; 32using OpenMetaverse;
@@ -96,6 +97,8 @@ namespace OpenSim.Region.Framework.Scenes
96 protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullID = new Dictionary<UUID, SceneObjectGroup>(); 97 protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullID = new Dictionary<UUID, SceneObjectGroup>();
97 private readonly Object m_dictionary_lock = new Object(); 98 private readonly Object m_dictionary_lock = new Object();
98 99
100 private Object m_updateLock = new Object();
101
99 #endregion 102 #endregion
100 103
101 protected internal SceneGraph(Scene parent, RegionInfo regInfo) 104 protected internal SceneGraph(Scene parent, RegionInfo regInfo)
@@ -369,6 +372,9 @@ namespace OpenSim.Region.Framework.Scenes
369 /// </summary> 372 /// </summary>
370 protected internal void UpdateObjectGroups() 373 protected internal void UpdateObjectGroups()
371 { 374 {
375 if (!Monitor.TryEnter(m_updateLock))
376 return;
377
372 List<SceneObjectGroup> updates; 378 List<SceneObjectGroup> updates;
373 379
374 // Some updates add more updates to the updateList. 380 // Some updates add more updates to the updateList.
@@ -395,6 +401,7 @@ namespace OpenSim.Region.Framework.Scenes
395 "[INNER SCENE]: Failed to update {0}, {1} - {2}", sog.Name, sog.UUID, e); 401 "[INNER SCENE]: Failed to update {0}, {1} - {2}", sog.Name, sog.UUID, e);
396 } 402 }
397 } 403 }
404 Monitor.Exit(m_updateLock);
398 } 405 }
399 406
400 protected internal void AddPhysicalPrim(int number) 407 protected internal void AddPhysicalPrim(int number)
@@ -1555,56 +1562,59 @@ namespace OpenSim.Region.Framework.Scenes
1555 /// <param name="childPrims"></param> 1562 /// <param name="childPrims"></param>
1556 protected internal void LinkObjects(IClientAPI client, uint parentPrimId, List<uint> childPrimIds) 1563 protected internal void LinkObjects(IClientAPI client, uint parentPrimId, List<uint> childPrimIds)
1557 { 1564 {
1558 SceneObjectGroup parentGroup = GetGroupByPrim(parentPrimId); 1565 lock (m_updateLock)
1559
1560 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1561 if (parentGroup != null)
1562 { 1566 {
1563 // We do this in reverse to get the link order of the prims correct 1567 SceneObjectGroup parentGroup = GetGroupByPrim(parentPrimId);
1564 for (int i = childPrimIds.Count - 1; i >= 0; i--) 1568
1569 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1570 if (parentGroup != null)
1565 { 1571 {
1566 SceneObjectGroup child = GetGroupByPrim(childPrimIds[i]); 1572 // We do this in reverse to get the link order of the prims correct
1567 if (child != null) 1573 for (int i = childPrimIds.Count - 1; i >= 0; i--)
1568 { 1574 {
1569 // Make sure no child prim is set for sale 1575 SceneObjectGroup child = GetGroupByPrim(childPrimIds[i]);
1570 // So that, on delink, no prims are unwittingly 1576 if (child != null)
1571 // left for sale and sold off 1577 {
1572 child.RootPart.ObjectSaleType = 0; 1578 // Make sure no child prim is set for sale
1573 child.RootPart.SalePrice = 10; 1579 // So that, on delink, no prims are unwittingly
1574 childGroups.Add(child); 1580 // left for sale and sold off
1581 child.RootPart.ObjectSaleType = 0;
1582 child.RootPart.SalePrice = 10;
1583 childGroups.Add(child);
1584 }
1575 } 1585 }
1576 } 1586 }
1577 } 1587 else
1578 else 1588 {
1579 { 1589 return; // parent is null so not in this region
1580 return; // parent is null so not in this region 1590 }
1581 }
1582 1591
1583 foreach (SceneObjectGroup child in childGroups) 1592 foreach (SceneObjectGroup child in childGroups)
1584 { 1593 {
1585 parentGroup.LinkToGroup(child); 1594 parentGroup.LinkToGroup(child);
1586 1595
1587 // this is here so physics gets updated! 1596 // this is here so physics gets updated!
1588 // Don't remove! Bad juju! Stay away! or fix physics! 1597 // Don't remove! Bad juju! Stay away! or fix physics!
1589 child.AbsolutePosition = child.AbsolutePosition; 1598 child.AbsolutePosition = child.AbsolutePosition;
1590 } 1599 }
1591 1600
1592 // We need to explicitly resend the newly link prim's object properties since no other actions 1601 // We need to explicitly resend the newly link prim's object properties since no other actions
1593 // occur on link to invoke this elsewhere (such as object selection) 1602 // occur on link to invoke this elsewhere (such as object selection)
1594 parentGroup.RootPart.AddFlag(PrimFlags.CreateSelected); 1603 parentGroup.RootPart.AddFlag(PrimFlags.CreateSelected);
1595 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1604 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1596 parentGroup.HasGroupChanged = true; 1605 parentGroup.HasGroupChanged = true;
1597 parentGroup.ScheduleGroupForFullUpdate(); 1606 parentGroup.ScheduleGroupForFullUpdate();
1598 1607
1599 if (client != null) 1608 if (client != null)
1600 {
1601 parentGroup.GetProperties(client);
1602 }
1603 else
1604 {
1605 foreach (ScenePresence p in GetScenePresences())
1606 { 1609 {
1607 parentGroup.GetProperties(p.ControllingClient); 1610 parentGroup.GetProperties(client);
1611 }
1612 else
1613 {
1614 foreach (ScenePresence p in GetScenePresences())
1615 {
1616 parentGroup.GetProperties(p.ControllingClient);
1617 }
1608 } 1618 }
1609 } 1619 }
1610 } 1620 }
@@ -1620,109 +1630,112 @@ namespace OpenSim.Region.Framework.Scenes
1620 1630
1621 protected internal void DelinkObjects(List<uint> primIds, bool sendEvents) 1631 protected internal void DelinkObjects(List<uint> primIds, bool sendEvents)
1622 { 1632 {
1623 List<SceneObjectPart> childParts = new List<SceneObjectPart>(); 1633 lock (m_updateLock)
1624 List<SceneObjectPart> rootParts = new List<SceneObjectPart>();
1625 List<SceneObjectGroup> affectedGroups = new List<SceneObjectGroup>();
1626 // Look them all up in one go, since that is comparatively expensive
1627 //
1628 foreach (uint primID in primIds)
1629 { 1634 {
1630 SceneObjectPart part = m_parentScene.GetSceneObjectPart(primID); 1635 List<SceneObjectPart> childParts = new List<SceneObjectPart>();
1631 if (part != null) 1636 List<SceneObjectPart> rootParts = new List<SceneObjectPart>();
1637 List<SceneObjectGroup> affectedGroups = new List<SceneObjectGroup>();
1638 // Look them all up in one go, since that is comparatively expensive
1639 //
1640 foreach (uint primID in primIds)
1632 { 1641 {
1633 if (part.LinkNum < 2) // Root or single 1642 SceneObjectPart part = m_parentScene.GetSceneObjectPart(primID);
1634 rootParts.Add(part); 1643 if (part != null)
1644 {
1645 if (part.LinkNum < 2) // Root or single
1646 rootParts.Add(part);
1647 else
1648 childParts.Add(part);
1649
1650 SceneObjectGroup group = part.ParentGroup;
1651 if (!affectedGroups.Contains(group))
1652 affectedGroups.Add(group);
1653 }
1635 else 1654 else
1636 childParts.Add(part); 1655 {
1637 1656 m_log.ErrorFormat("Viewer requested unlink of nonexistent part {0}", primID);
1638 SceneObjectGroup group = part.ParentGroup; 1657 }
1639 if (!affectedGroups.Contains(group))
1640 affectedGroups.Add(group);
1641 } 1658 }
1642 else 1659
1660 foreach (SceneObjectPart child in childParts)
1643 { 1661 {
1644 m_log.ErrorFormat("Viewer requested unlink of nonexistent part {0}", primID); 1662 // Unlink all child parts from their groups
1663 //
1664 child.ParentGroup.DelinkFromGroup(child, sendEvents);
1645 } 1665 }
1646 }
1647 1666
1648 foreach (SceneObjectPart child in childParts) 1667 foreach (SceneObjectPart root in rootParts)
1649 {
1650 // Unlink all child parts from their groups
1651 //
1652 child.ParentGroup.DelinkFromGroup(child, sendEvents);
1653 }
1654
1655 foreach (SceneObjectPart root in rootParts)
1656 {
1657 // In most cases, this will run only one time, and the prim
1658 // will be a solo prim
1659 // However, editing linked parts and unlinking may be different
1660 //
1661 SceneObjectGroup group = root.ParentGroup;
1662 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Children.Values);
1663 int numChildren = group.Children.Count;
1664
1665 // If there are prims left in a link set, but the root is
1666 // slated for unlink, we need to do this
1667 //
1668 if (numChildren != 1)
1669 { 1668 {
1670 // Unlink the remaining set 1669 // In most cases, this will run only one time, and the prim
1670 // will be a solo prim
1671 // However, editing linked parts and unlinking may be different
1671 // 1672 //
1672 bool sendEventsToRemainder = true; 1673 SceneObjectGroup group = root.ParentGroup;
1673 if (numChildren > 1) 1674 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Children.Values);
1674 sendEventsToRemainder = false; 1675 int numChildren = group.Children.Count;
1675
1676 foreach (SceneObjectPart p in newSet)
1677 {
1678 if (p != group.RootPart)
1679 group.DelinkFromGroup(p, sendEventsToRemainder);
1680 }
1681 1676
1682 // If there is more than one prim remaining, we 1677 // If there are prims left in a link set, but the root is
1683 // need to re-link 1678 // slated for unlink, we need to do this
1684 // 1679 //
1685 if (numChildren > 2) 1680 if (numChildren != 1)
1686 { 1681 {
1687 // Remove old root 1682 // Unlink the remaining set
1688 // 1683 //
1689 if (newSet.Contains(root)) 1684 bool sendEventsToRemainder = true;
1690 newSet.Remove(root); 1685 if (numChildren > 1)
1686 sendEventsToRemainder = false;
1691 1687
1692 // Preserve link ordering 1688 foreach (SceneObjectPart p in newSet)
1693 //
1694 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1695 { 1689 {
1696 return a.LinkNum.CompareTo(b.LinkNum); 1690 if (p != group.RootPart)
1697 }); 1691 group.DelinkFromGroup(p, sendEventsToRemainder);
1692 }
1698 1693
1699 // Determine new root 1694 // If there is more than one prim remaining, we
1695 // need to re-link
1700 // 1696 //
1701 SceneObjectPart newRoot = newSet[0]; 1697 if (numChildren > 2)
1702 newSet.RemoveAt(0); 1698 {
1699 // Remove old root
1700 //
1701 if (newSet.Contains(root))
1702 newSet.Remove(root);
1703
1704 // Preserve link ordering
1705 //
1706 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1707 {
1708 return a.LinkNum.CompareTo(b.LinkNum);
1709 });
1703 1710
1704 List<uint> linkIDs = new List<uint>(); 1711 // Determine new root
1712 //
1713 SceneObjectPart newRoot = newSet[0];
1714 newSet.RemoveAt(0);
1705 1715
1706 foreach (SceneObjectPart newChild in newSet) 1716 List<uint> linkIDs = new List<uint>();
1707 { 1717
1708 newChild.UpdateFlag = 0; 1718 foreach (SceneObjectPart newChild in newSet)
1709 linkIDs.Add(newChild.LocalId); 1719 {
1710 } 1720 newChild.UpdateFlag = 0;
1721 linkIDs.Add(newChild.LocalId);
1722 }
1711 1723
1712 LinkObjects(null, newRoot.LocalId, linkIDs); 1724 LinkObjects(null, newRoot.LocalId, linkIDs);
1713 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1725 if (!affectedGroups.Contains(newRoot.ParentGroup))
1714 affectedGroups.Add(newRoot.ParentGroup); 1726 affectedGroups.Add(newRoot.ParentGroup);
1727 }
1715 } 1728 }
1716 } 1729 }
1717 }
1718 1730
1719 // Finally, trigger events in the roots 1731 // Finally, trigger events in the roots
1720 // 1732 //
1721 foreach (SceneObjectGroup g in affectedGroups) 1733 foreach (SceneObjectGroup g in affectedGroups)
1722 { 1734 {
1723 g.TriggerScriptChangedEvent(Changed.LINK); 1735 g.TriggerScriptChangedEvent(Changed.LINK);
1724 g.HasGroupChanged = true; // Persist 1736 g.HasGroupChanged = true; // Persist
1725 g.ScheduleGroupForFullUpdate(); 1737 g.ScheduleGroupForFullUpdate();
1738 }
1726 } 1739 }
1727 } 1740 }
1728 1741