diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 876c7c9c70..e938137764 100755 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -582,58 +582,6 @@ namespace OpenSim.Framework public float dwell; } - public class EntityUpdate - { - private readonly ISceneEntity m_entity; - private PrimUpdateFlags m_flags; - - public ISceneEntity Entity - { - get { return m_entity; } - } - - public PrimUpdateFlags Flags - { - get { return m_flags; } - set { m_flags = value; } - } - - public virtual void Update() - { - // we are on the new one - if ((m_flags & PrimUpdateFlags.CancelKill) != 0) - { - if ((m_flags & PrimUpdateFlags.UpdateProbe) != 0) - m_flags = PrimUpdateFlags.UpdateProbe; - else - m_flags = PrimUpdateFlags.FullUpdatewithAnim; - } - } - - public virtual void Update(EntityUpdate oldupdate) - { - // we are on the new one - PrimUpdateFlags updateFlags = oldupdate.Flags; - if ((m_flags & PrimUpdateFlags.UpdateProbe) != 0) - updateFlags &= ~PrimUpdateFlags.UpdateProbe; - if ((m_flags & PrimUpdateFlags.CancelKill) != 0) - { - if ((m_flags & PrimUpdateFlags.UpdateProbe) != 0) - m_flags = PrimUpdateFlags.UpdateProbe; - else - m_flags = PrimUpdateFlags.FullUpdatewithAnim; - } - else - m_flags |= updateFlags; - } - - public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags) - { - m_entity = entity; - m_flags = flags; - } - } - public class PlacesReplyData { public UUID OwnerID; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 96830be21f..9436abc2cb 100755 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5959,25 +5959,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task); } - private class ObjectPropertyUpdate : EntityUpdate - { - internal bool SendFamilyProps; - internal bool SendObjectProps; - - public ObjectPropertyUpdate(ISceneEntity entity, uint flags, bool sendfam, bool sendobj) - : base(entity,(PrimUpdateFlags)flags) - { - SendFamilyProps = sendfam; - SendObjectProps = sendobj; - } - public void Update(ObjectPropertyUpdate update) - { - SendFamilyProps = SendFamilyProps || update.SendFamilyProps; - SendObjectProps = SendObjectProps || update.SendObjectProps; - // other properties may need to be updated by base class - base.Update(update); - } - } public void SendObjectPropertiesFamilyData(ISceneEntity entity, uint requestFlags) { @@ -6061,7 +6042,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } ObjectPropertyUpdate update = (ObjectPropertyUpdate)iupdate; - if (update.SendFamilyProps) + if ((update.PropsFlags & ObjectPropertyUpdateFlags.Family) != 0) { if (update.Entity is SceneObjectPart) { @@ -6073,7 +6054,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - if (update.SendObjectProps) + if ((update.PropsFlags & ObjectPropertyUpdateFlags.Object) != 0) { if (update.Entity is SceneObjectPart) { @@ -6113,6 +6094,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP lastpos = zc.Position; lastzc = zc.ZeroCount; CreateObjectPropertiesBlock((SceneObjectPart)eu.Entity, zc); + eu.Free(); if (zc.Position < LLUDPServer.MAXPAYLOAD) { //tau.Add(eu); @@ -6172,6 +6154,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP zc.Position = 8; CreateObjectPropertiesFamilyBlock((SceneObjectPart)eu.Entity, eu.Flags, zc); + eu.Free(); buf.DataLength = zc.Finish(); //List tau = new List(1); //tau.Add(new ObjectPropertyUpdate((ISceneEntity) eu, (uint)eu.Flags, true, false)); diff --git a/OpenSim/Region/Framework/Scenes/EntityUpdates.cs b/OpenSim/Region/Framework/Scenes/EntityUpdates.cs new file mode 100644 index 0000000000..dca2c68c7b --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/EntityUpdates.cs @@ -0,0 +1,204 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using OpenSim.Framework; + +namespace OpenSim.Region.Framework.Scenes +{ + /// + /// Specifies the fields that have been changed when sending a prim or + /// avatar update + /// + [Flags] + public enum ObjectPropertyUpdateFlags : byte + { + None = 0, + Family = 1, + Object = 2, + + NoFamily = unchecked((byte)~Family), + NoObject = unchecked((byte)~Object) + } + + public class EntityUpdate : IComparable + { + + // for priority queue + private uint m_pqueue; + private ulong m_entryorder; + + private ISceneEntity m_entity; + private PrimUpdateFlags m_flags; + public ObjectPropertyUpdateFlags m_propsFlags; + + public uint PriorityQueue + { + get + { + return m_pqueue; + } + set + { + m_pqueue = value; + } + } + + public ulong EntryOrder + { + get + { + return m_entryorder; + } + set + { + m_entryorder = value; + } + } + + public ObjectPropertyUpdateFlags PropsFlags + { + get + { + return m_propsFlags; + } + set + { + m_propsFlags = value; + } + } + + public ISceneEntity Entity + { + get { return m_entity; } + } + + public PrimUpdateFlags Flags + { + get { return m_flags; } + set { m_flags = value; } + } + + public virtual void Update() + { + // we are on the new one + if ((m_flags & PrimUpdateFlags.CancelKill) != 0) + { + if ((m_flags & PrimUpdateFlags.UpdateProbe) != 0) + m_flags = PrimUpdateFlags.UpdateProbe; + else + m_flags = PrimUpdateFlags.FullUpdatewithAnim; + } + } + + public void Update(uint pqueue, ulong entry) + { + Update(); + m_pqueue = pqueue; + m_entryorder = entry; + } + + public void Update(EntityUpdate oldupdate) + { + // we are on the new one + PrimUpdateFlags updateFlags = oldupdate.Flags; + if ((m_flags & PrimUpdateFlags.UpdateProbe) != 0) + updateFlags &= ~PrimUpdateFlags.UpdateProbe; + if ((m_flags & PrimUpdateFlags.CancelKill) != 0) + { + if ((m_flags & PrimUpdateFlags.UpdateProbe) != 0) + m_flags = PrimUpdateFlags.UpdateProbe; + else + m_flags = PrimUpdateFlags.FullUpdatewithAnim; + } + else + m_flags |= updateFlags; + } + + public void Update(EntityUpdate oldupdate, uint pqueue, ulong entry) + { + Update(oldupdate); + m_pqueue = pqueue; + m_entryorder = entry; + } + + public void Free() + { + m_entity = null; + } + + public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags) + { + m_entity = entity; + m_flags = flags; + } + + public override string ToString() + { + return String.Format("[{0},{1},{2}]", m_pqueue, m_entryorder, m_entity.LocalId); + } + + public int CompareTo(EntityUpdate other) + { + // I'm assuming that the root part of an SOG is added to the update queue + // before the component parts + return Comparer.Default.Compare(this.EntryOrder, other.EntryOrder); + } + } + + public class ObjectPropertyUpdate : EntityUpdate + { + public ObjectPropertyUpdate(ISceneEntity entity, uint flags, bool sendfam, bool sendobj) + : base(entity, (PrimUpdateFlags)flags) + { + if (sendfam) + m_propsFlags |= ObjectPropertyUpdateFlags.Family; + else + m_propsFlags &= ObjectPropertyUpdateFlags.NoFamily; + + if (sendobj) + m_propsFlags |= ObjectPropertyUpdateFlags.Object; + else + m_propsFlags &= ObjectPropertyUpdateFlags.NoObject; + } + + public void Update(ObjectPropertyUpdate update) + { + m_propsFlags |= update.PropsFlags; + // other properties may need to be updated by base class + base.Update(update); + } + + public void Update(ObjectPropertyUpdate update, uint pqueue, ulong entry) + { + m_propsFlags |= update.PropsFlags; + // other properties may need to be updated by base class + base.Update(update, pqueue, entry); + } + } +} diff --git a/OpenSim/Framework/PriorityQueue.cs b/OpenSim/Region/Framework/Scenes/PriorityQueue.cs similarity index 73% rename from OpenSim/Framework/PriorityQueue.cs rename to OpenSim/Region/Framework/Scenes/PriorityQueue.cs index 53b4f8c738..0f5b792951 100644 --- a/OpenSim/Framework/PriorityQueue.cs +++ b/OpenSim/Region/Framework/Scenes/PriorityQueue.cs @@ -26,15 +26,10 @@ */ using System; -using System.Collections; using System.Collections.Generic; -using System.Reflection; - using OpenSim.Framework; -using OpenSim.Framework.Client; -using log4net; -namespace OpenSim.Framework +namespace OpenSim.Region.Framework.Scenes { public class PriorityQueue { @@ -56,7 +51,7 @@ namespace OpenSim.Framework private static readonly uint[] m_queueCounts = {0, 0, 8, 8, 5, 4, 3, 2, 1, 1, 1, 1, 1 }; // this is ava, ava, attach, <10m, 20,40,80,160m,320,640,1280, + - private MinHeap[] m_heaps = new MinHeap[NumberOfQueues]; + private MinHeap[] m_heaps = new MinHeap[NumberOfQueues]; private Dictionary m_lookupTable; // internal state used to ensure the deqeues are spread across the priority @@ -70,7 +65,7 @@ namespace OpenSim.Framework // next request is a counter of the number of updates queued, it provides // a total ordering on the updates coming through the queue and is more // lightweight (and more discriminating) than tick count - private UInt64 m_nextRequest = 0; + private ulong m_nextRequest = 0; /// /// Lock for enqueue and dequeue operations on the priority queue @@ -81,7 +76,7 @@ namespace OpenSim.Framework } #region constructor - public PriorityQueue() : this(MinHeap.DEFAULT_CAPACITY) { } + public PriorityQueue() : this(MinHeap.DEFAULT_CAPACITY) { } public PriorityQueue(int capacity) { @@ -89,7 +84,7 @@ namespace OpenSim.Framework capacity /= 4; for (int i = 0; i < m_heaps.Length; ++i) - m_heaps[i] = new MinHeap(capacity); + m_heaps[i] = new MinHeap(capacity); m_lookupTable = new Dictionary(m_capacity); m_nextQueue = NumberOfImmediateQueues; @@ -130,35 +125,35 @@ namespace OpenSim.Framework { LookupItem lookup; IHandle lookupH; - UInt64 entry; + ulong entry; uint localid = value.Entity.LocalId; if (m_lookupTable.TryGetValue(localid, out lookup)) { lookupH = lookup.Handle; entry = lookup.Heap[lookupH].EntryOrder; - EntityUpdate up = lookup.Heap[lookupH].Value; - value.Update(lookup.Heap[lookupH].Value); + EntityUpdate up = lookup.Heap[lookupH]; lookup.Heap.Remove(lookupH); if((up.Flags & PrimUpdateFlags.CancelKill) != 0) entry = m_nextRequest++; pqueue = Util.Clamp(pqueue, 0, NumberOfQueues - 1); + value.Update(up, pqueue, entry); + lookup.Heap = m_heaps[pqueue]; - lookup.Heap.Add(new MinHeapItem(pqueue, entry, value), ref lookup.Handle); + lookup.Heap.Add(value, ref lookup.Handle); m_lookupTable[localid] = lookup; return true; } - value.Update(); - entry = m_nextRequest++; ++m_added; - pqueue = Util.Clamp(pqueue, 0, NumberOfQueues - 1); + value.Update(pqueue, entry); + lookup.Heap = m_heaps[pqueue]; - lookup.Heap.Add(new MinHeapItem(pqueue, entry, value), ref lookup.Handle); + lookup.Heap.Add(value, ref lookup.Handle); m_lookupTable[localid] = lookup; return true; @@ -197,10 +192,8 @@ namespace OpenSim.Framework { if (m_heaps[iq].Count > 0) { - MinHeapItem item = m_heaps[iq].RemoveMin(); - m_lookupTable.Remove(item.Value.Entity.LocalId); - value = item.Value; - + value = m_heaps[iq].RemoveMin(); + m_lookupTable.Remove(value.Entity.LocalId); return true; } } @@ -211,15 +204,14 @@ namespace OpenSim.Framework // to give lower numbered queues a higher priority and higher percentage // of the bandwidth. - MinHeap curheap = m_heaps[m_nextQueue]; + MinHeap curheap = m_heaps[m_nextQueue]; // Check for more items to be pulled from the current queue if (m_countFromQueue > 0 && curheap.Count > 0) { --m_countFromQueue; - MinHeapItem item = curheap.RemoveMin(); - m_lookupTable.Remove(item.Value.Entity.LocalId); - value = item.Value; + value = curheap.RemoveMin(); + m_lookupTable.Remove(value.Entity.LocalId); return true; } @@ -237,9 +229,8 @@ namespace OpenSim.Framework m_countFromQueue = m_queueCounts[m_nextQueue]; --m_countFromQueue; - MinHeapItem item = curheap.RemoveMin(); - m_lookupTable.Remove(item.Value.Entity.LocalId); - value = item.Value; + value = curheap.RemoveMin(); + m_lookupTable.Remove(value.Entity.LocalId); return true; } @@ -256,12 +247,11 @@ namespace OpenSim.Framework { for (int iq = 0; iq < NumberOfQueues; ++iq) { - MinHeap curheap = m_heaps[iq]; + MinHeap curheap = m_heaps[iq]; if (curheap.Count > 0) { - MinHeapItem item = curheap.RemoveMin(); - m_lookupTable.Remove(item.Value.Entity.LocalId); - value = item.Value; + value = curheap.RemoveMin(); + m_lookupTable.Remove(value.Entity.LocalId); return true; } } @@ -281,32 +271,33 @@ namespace OpenSim.Framework /// (m_lookupTable.Values)) { - if (lookup.Heap.TryGetValue(lookup.Handle, out item)) + if (lookup.Heap.TryGetValue(lookup.Handle, out currentEU)) { - if (handler(ref pqueue, item.Value.Entity)) + if (handler(ref pqueue, currentEU.Entity)) { // unless the priority queue has changed, there is no need to modify // the entry pqueue = Util.Clamp(pqueue, 0, NumberOfQueues - 1); - if (pqueue != item.PriorityQueue) + if (pqueue != currentEU.PriorityQueue) { - lookup.Heap.Remove(lookup.Handle); + currentEU.PriorityQueue = pqueue; + lookup.Heap.Remove(lookup.Handle); LookupItem litem = lookup; litem.Heap = m_heaps[pqueue]; - litem.Heap.Add(new MinHeapItem(pqueue, item), ref litem.Handle); - m_lookupTable[item.Value.Entity.LocalId] = litem; + litem.Heap.Add(currentEU, ref litem.Handle); + m_lookupTable[currentEU.Entity.LocalId] = litem; } } else { // m_log.WarnFormat("[PQUEUE]: UpdatePriorityHandler returned false for {0}",item.Value.Entity.UUID); lookup.Heap.Remove(lookup.Handle); - m_lookupTable.Remove(item.Value.Entity.LocalId); + m_lookupTable.Remove(currentEU.Entity.LocalId); } } } @@ -324,68 +315,11 @@ namespace OpenSim.Framework #endregion PublicMethods -#region MinHeapItem - private struct MinHeapItem : IComparable - { - private EntityUpdate value; - internal EntityUpdate Value - { - get - { - return value; - } - } - - private uint pqueue; - internal uint PriorityQueue - { - get - { - return pqueue; - } - } - - private UInt64 entryorder; - internal UInt64 EntryOrder - { - get - { - return entryorder; - } - } - - internal MinHeapItem(uint _pqueue, MinHeapItem other) - { - entryorder = other.entryorder; - value = other.value; - pqueue = _pqueue; - } - - internal MinHeapItem(uint _pqueue, UInt64 _entryorder, EntityUpdate _value) - { - entryorder = _entryorder; - value = _value; - pqueue = _pqueue; - } - - public override string ToString() - { - return String.Format("[{0},{1},{2}]",pqueue,entryorder,value.Entity.LocalId); - } - - public int CompareTo(MinHeapItem other) - { - // I'm assuming that the root part of an SOG is added to the update queue - // before the component parts - return Comparer.Default.Compare(this.EntryOrder, other.EntryOrder); - } - } -#endregion #region LookupItem private struct LookupItem { - internal MinHeap Heap; + internal MinHeap Heap; internal IHandle Handle; } #endregion