aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs237
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs245
2 files changed, 266 insertions, 216 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index e9e1fa3..8de31d7 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -3687,12 +3687,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3687 avgTimeDilation += update.TimeDilation; 3687 avgTimeDilation += update.TimeDilation;
3688 avgTimeDilation *= 0.5f; 3688 avgTimeDilation *= 0.5f;
3689 3689
3690// <MIC>
3691// DEBUGGING CODE... REMOVE
3692// if (update.Entity is ScenePresence)
3693// LogAvatarUpdateEvent(this.m_agentId,update.Entity.UUID,timeinqueue);
3694// </MIC>
3695
3696 if (update.Entity is SceneObjectPart) 3690 if (update.Entity is SceneObjectPart)
3697 { 3691 {
3698 SceneObjectPart part = (SceneObjectPart)update.Entity; 3692 SceneObjectPart part = (SceneObjectPart)update.Entity;
@@ -5017,7 +5011,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5017 AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest); 5011 AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest);
5018 AddLocalPacketHandler(PacketType.UUIDNameRequest, HandleUUIDNameRequest, false); 5012 AddLocalPacketHandler(PacketType.UUIDNameRequest, HandleUUIDNameRequest, false);
5019 AddLocalPacketHandler(PacketType.RegionHandleRequest, HandleRegionHandleRequest); 5013 AddLocalPacketHandler(PacketType.RegionHandleRequest, HandleRegionHandleRequest);
5020 AddLocalPacketHandler(PacketType.ParcelInfoRequest, HandleParcelInfoRequest, false); 5014 AddLocalPacketHandler(PacketType.ParcelInfoRequest, HandleParcelInfoRequest);
5021 AddLocalPacketHandler(PacketType.ParcelAccessListRequest, HandleParcelAccessListRequest, false); 5015 AddLocalPacketHandler(PacketType.ParcelAccessListRequest, HandleParcelAccessListRequest, false);
5022 AddLocalPacketHandler(PacketType.ParcelAccessListUpdate, HandleParcelAccessListUpdate, false); 5016 AddLocalPacketHandler(PacketType.ParcelAccessListUpdate, HandleParcelAccessListUpdate, false);
5023 AddLocalPacketHandler(PacketType.ParcelPropertiesRequest, HandleParcelPropertiesRequest, false); 5017 AddLocalPacketHandler(PacketType.ParcelPropertiesRequest, HandleParcelPropertiesRequest, false);
@@ -8888,13 +8882,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8888 case "instantmessage": 8882 case "instantmessage":
8889 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) 8883 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
8890 { 8884 {
8891 if (messagePacket.ParamList.Length < 5) 8885 if (messagePacket.ParamList.Length < 2)
8892 return true; 8886 return true;
8887
8893 UUID invoice = messagePacket.MethodData.Invoice; 8888 UUID invoice = messagePacket.MethodData.Invoice;
8894 UUID SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter));
8895 string SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter);
8896 string Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter);
8897 UUID sessionID = messagePacket.AgentData.SessionID; 8889 UUID sessionID = messagePacket.AgentData.SessionID;
8890
8891 UUID SenderID;
8892 string SenderName;
8893 string Message;
8894
8895 if (messagePacket.ParamList.Length < 5)
8896 {
8897 SenderID = AgentId;
8898 SenderName = Utils.BytesToString(messagePacket.ParamList[0].Parameter);
8899 Message = Utils.BytesToString(messagePacket.ParamList[1].Parameter);
8900 }
8901 else
8902 {
8903 SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter));
8904 SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter);
8905 Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter);
8906 }
8907
8898 OnEstateBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message); 8908 OnEstateBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message);
8899 } 8909 }
8900 return true; 8910 return true;
@@ -11789,209 +11799,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11789 OutPacket(pack, ThrottleOutPacketType.Task); 11799 OutPacket(pack, ThrottleOutPacketType.Task);
11790 } 11800 }
11791 11801
11792 #region PriorityQueue
11793 public class PriorityQueue
11794 {
11795 internal delegate bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity);
11796
11797 // Heap[0] for self updates
11798 // Heap[1..12] for entity updates
11799
11800 internal const uint m_numberOfQueues = 12;
11801 private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[m_numberOfQueues];
11802 private Dictionary<uint, LookupItem> m_lookupTable;
11803 private object m_syncRoot = new object();
11804 private uint m_nextQueue = 0;
11805 private UInt64 m_nextRequest = 0;
11806
11807 internal PriorityQueue() :
11808 this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY) { }
11809 internal PriorityQueue(int capacity)
11810 {
11811 m_lookupTable = new Dictionary<uint, LookupItem>(capacity);
11812
11813 for (int i = 0; i < m_heaps.Length; ++i)
11814 m_heaps[i] = new MinHeap<MinHeapItem>(capacity);
11815 }
11816
11817 public object SyncRoot { get { return this.m_syncRoot; } }
11818
11819 internal int Count
11820 {
11821 get
11822 {
11823 int count = 0;
11824 for (int i = 0; i < m_heaps.Length; ++i)
11825 count += m_heaps[i].Count;
11826 return count;
11827 }
11828 }
11829
11830 public bool Enqueue(uint pqueue, EntityUpdate value)
11831 {
11832 LookupItem lookup;
11833
11834 uint localid = value.Entity.LocalId;
11835 UInt64 entry = m_nextRequest++;
11836 if (m_lookupTable.TryGetValue(localid, out lookup))
11837 {
11838 entry = lookup.Heap[lookup.Handle].EntryOrder;
11839 value.Flags |= lookup.Heap[lookup.Handle].Value.Flags;
11840 lookup.Heap.Remove(lookup.Handle);
11841 }
11842
11843 pqueue = Util.Clamp<uint>(pqueue, 0, m_numberOfQueues - 1);
11844 lookup.Heap = m_heaps[pqueue];
11845 lookup.Heap.Add(new MinHeapItem(pqueue, entry, value), ref lookup.Handle);
11846 m_lookupTable[localid] = lookup;
11847
11848 return true;
11849 }
11850
11851 internal bool TryDequeue(out EntityUpdate value, out Int32 timeinqueue)
11852 {
11853 for (int i = 0; i < m_numberOfQueues; ++i)
11854 {
11855 // To get the fair queing, we cycle through each of the
11856 // queues when finding an element to dequeue, this code
11857 // assumes that the distribution of updates in the queues
11858 // is polynomial, probably quadractic (eg distance of PI * R^2)
11859 uint h = (uint)((m_nextQueue + i) % m_numberOfQueues);
11860 if (m_heaps[h].Count > 0)
11861 {
11862 m_nextQueue = (uint)((h + 1) % m_numberOfQueues);
11863
11864 MinHeapItem item = m_heaps[h].RemoveMin();
11865 m_lookupTable.Remove(item.Value.Entity.LocalId);
11866 timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
11867 value = item.Value;
11868
11869 return true;
11870 }
11871 }
11872
11873 timeinqueue = 0;
11874 value = default(EntityUpdate);
11875 return false;
11876 }
11877
11878 internal void Reprioritize(UpdatePriorityHandler handler)
11879 {
11880 MinHeapItem item;
11881 foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values))
11882 {
11883 if (lookup.Heap.TryGetValue(lookup.Handle, out item))
11884 {
11885 uint pqueue = item.PriorityQueue;
11886 uint localid = item.Value.Entity.LocalId;
11887
11888 if (handler(ref pqueue, item.Value.Entity))
11889 {
11890 // unless the priority queue has changed, there is no need to modify
11891 // the entry
11892 pqueue = Util.Clamp<uint>(pqueue, 0, m_numberOfQueues - 1);
11893 if (pqueue != item.PriorityQueue)
11894 {
11895 lookup.Heap.Remove(lookup.Handle);
11896
11897 LookupItem litem = lookup;
11898 litem.Heap = m_heaps[pqueue];
11899 litem.Heap.Add(new MinHeapItem(pqueue, item), ref litem.Handle);
11900 m_lookupTable[localid] = litem;
11901 }
11902 }
11903 else
11904 {
11905 m_log.WarnFormat("[LLCLIENTVIEW]: UpdatePriorityHandler returned false for {0}",item.Value.Entity.UUID);
11906 lookup.Heap.Remove(lookup.Handle);
11907 this.m_lookupTable.Remove(localid);
11908 }
11909 }
11910 }
11911 }
11912
11913 public override string ToString()
11914 {
11915 string s = "";
11916 for (int i = 0; i < m_numberOfQueues; i++)
11917 {
11918 if (s != "") s += ",";
11919 s += m_heaps[i].Count.ToString();
11920 }
11921 return s;
11922 }
11923
11924 #region MinHeapItem
11925 private struct MinHeapItem : IComparable<MinHeapItem>
11926 {
11927 private EntityUpdate value;
11928 internal EntityUpdate Value {
11929 get {
11930 return this.value;
11931 }
11932 }
11933
11934 private uint pqueue;
11935 internal uint PriorityQueue {
11936 get {
11937 return this.pqueue;
11938 }
11939 }
11940
11941 private Int32 entrytime;
11942 internal Int32 EntryTime {
11943 get {
11944 return this.entrytime;
11945 }
11946 }
11947
11948 private UInt64 entryorder;
11949 internal UInt64 EntryOrder
11950 {
11951 get {
11952 return this.entryorder;
11953 }
11954 }
11955
11956 internal MinHeapItem(uint pqueue, MinHeapItem other)
11957 {
11958 this.entrytime = other.entrytime;
11959 this.entryorder = other.entryorder;
11960 this.value = other.value;
11961 this.pqueue = pqueue;
11962 }
11963
11964 internal MinHeapItem(uint pqueue, UInt64 entryorder, EntityUpdate value)
11965 {
11966 this.entrytime = Util.EnvironmentTickCount();
11967 this.entryorder = entryorder;
11968 this.value = value;
11969 this.pqueue = pqueue;
11970 }
11971
11972 public override string ToString()
11973 {
11974 return String.Format("[{0},{1},{2}]",pqueue,entryorder,value.Entity.LocalId);
11975 }
11976
11977 public int CompareTo(MinHeapItem other)
11978 {
11979 // I'm assuming that the root part of an SOG is added to the update queue
11980 // before the component parts
11981 return Comparer<UInt64>.Default.Compare(this.EntryOrder, other.EntryOrder);
11982 }
11983 }
11984 #endregion
11985
11986 #region LookupItem
11987 private struct LookupItem
11988 {
11989 internal MinHeap<MinHeapItem> Heap;
11990 internal IHandle Handle;
11991 }
11992 #endregion
11993 }
11994
11995 public struct PacketProcessor 11802 public struct PacketProcessor
11996 { 11803 {
11997 public PacketMethod method; 11804 public PacketMethod method;
@@ -12012,8 +11819,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12012 } 11819 }
12013 } 11820 }
12014 11821
12015 #endregion
12016
12017 public static OSD BuildEvent(string eventName, OSD eventBody) 11822 public static OSD BuildEvent(string eventName, OSD eventBody)
12018 { 11823 {
12019 OSDMap osdEvent = new OSDMap(2); 11824 OSDMap osdEvent = new OSDMap(2);
diff --git a/OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs b/OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs
new file mode 100644
index 0000000..364ce4b
--- /dev/null
+++ b/OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs
@@ -0,0 +1,245 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32
33using OpenSim.Framework;
34using OpenSim.Framework.Client;
35using log4net;
36
37namespace OpenSim.Region.ClientStack.LindenUDP
38{
39 public class PriorityQueue
40 {
41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
42
43 internal delegate bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity);
44
45 // Heap[0] for self updates
46 // Heap[1..12] for entity updates
47
48 internal const uint m_numberOfQueues = 12;
49
50 private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[m_numberOfQueues];
51 private Dictionary<uint, LookupItem> m_lookupTable;
52 private uint m_nextQueue = 0;
53 private UInt64 m_nextRequest = 0;
54
55 private object m_syncRoot = new object();
56 public object SyncRoot {
57 get { return this.m_syncRoot; }
58 }
59
60 internal PriorityQueue() : this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY) { }
61
62 internal PriorityQueue(int capacity)
63 {
64 m_lookupTable = new Dictionary<uint, LookupItem>(capacity);
65
66 for (int i = 0; i < m_heaps.Length; ++i)
67 m_heaps[i] = new MinHeap<MinHeapItem>(capacity);
68 }
69
70 internal int Count
71 {
72 get
73 {
74 int count = 0;
75 for (int i = 0; i < m_heaps.Length; ++i)
76 count += m_heaps[i].Count;
77 return count;
78 }
79 }
80
81 public bool Enqueue(uint pqueue, EntityUpdate value)
82 {
83 LookupItem lookup;
84
85 uint localid = value.Entity.LocalId;
86 UInt64 entry = m_nextRequest++;
87 if (m_lookupTable.TryGetValue(localid, out lookup))
88 {
89 entry = lookup.Heap[lookup.Handle].EntryOrder;
90 value.Flags |= lookup.Heap[lookup.Handle].Value.Flags;
91 lookup.Heap.Remove(lookup.Handle);
92 }
93
94 pqueue = Util.Clamp<uint>(pqueue, 0, m_numberOfQueues - 1);
95 lookup.Heap = m_heaps[pqueue];
96 lookup.Heap.Add(new MinHeapItem(pqueue, entry, value), ref lookup.Handle);
97 m_lookupTable[localid] = lookup;
98
99 return true;
100 }
101
102 internal bool TryDequeue(out EntityUpdate value, out Int32 timeinqueue)
103 {
104 for (int i = 0; i < m_numberOfQueues; ++i)
105 {
106 // To get the fair queing, we cycle through each of the
107 // queues when finding an element to dequeue, this code
108 // assumes that the distribution of updates in the queues
109 // is polynomial, probably quadractic (eg distance of PI * R^2)
110 uint h = (uint)((m_nextQueue + i) % m_numberOfQueues);
111 if (m_heaps[h].Count > 0)
112 {
113 m_nextQueue = (uint)((h + 1) % m_numberOfQueues);
114
115 MinHeapItem item = m_heaps[h].RemoveMin();
116 m_lookupTable.Remove(item.Value.Entity.LocalId);
117 timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
118 value = item.Value;
119
120 return true;
121 }
122 }
123
124 timeinqueue = 0;
125 value = default(EntityUpdate);
126 return false;
127 }
128
129 internal void Reprioritize(UpdatePriorityHandler handler)
130 {
131 MinHeapItem item;
132 foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values))
133 {
134 if (lookup.Heap.TryGetValue(lookup.Handle, out item))
135 {
136 uint pqueue = item.PriorityQueue;
137 uint localid = item.Value.Entity.LocalId;
138
139 if (handler(ref pqueue, item.Value.Entity))
140 {
141 // unless the priority queue has changed, there is no need to modify
142 // the entry
143 pqueue = Util.Clamp<uint>(pqueue, 0, m_numberOfQueues - 1);
144 if (pqueue != item.PriorityQueue)
145 {
146 lookup.Heap.Remove(lookup.Handle);
147
148 LookupItem litem = lookup;
149 litem.Heap = m_heaps[pqueue];
150 litem.Heap.Add(new MinHeapItem(pqueue, item), ref litem.Handle);
151 m_lookupTable[localid] = litem;
152 }
153 }
154 else
155 {
156 // m_log.WarnFormat("[PQUEUE]: UpdatePriorityHandler returned false for {0}",item.Value.Entity.UUID);
157 lookup.Heap.Remove(lookup.Handle);
158 this.m_lookupTable.Remove(localid);
159 }
160 }
161 }
162 }
163
164 public override string ToString()
165 {
166 string s = "";
167 for (int i = 0; i < m_numberOfQueues; i++)
168 {
169 if (s != "") s += ",";
170 s += m_heaps[i].Count.ToString();
171 }
172 return s;
173 }
174
175#region MinHeapItem
176 private struct MinHeapItem : IComparable<MinHeapItem>
177 {
178 private EntityUpdate value;
179 internal EntityUpdate Value {
180 get {
181 return this.value;
182 }
183 }
184
185 private uint pqueue;
186 internal uint PriorityQueue {
187 get {
188 return this.pqueue;
189 }
190 }
191
192 private Int32 entrytime;
193 internal Int32 EntryTime {
194 get {
195 return this.entrytime;
196 }
197 }
198
199 private UInt64 entryorder;
200 internal UInt64 EntryOrder
201 {
202 get {
203 return this.entryorder;
204 }
205 }
206
207 internal MinHeapItem(uint pqueue, MinHeapItem other)
208 {
209 this.entrytime = other.entrytime;
210 this.entryorder = other.entryorder;
211 this.value = other.value;
212 this.pqueue = pqueue;
213 }
214
215 internal MinHeapItem(uint pqueue, UInt64 entryorder, EntityUpdate value)
216 {
217 this.entrytime = Util.EnvironmentTickCount();
218 this.entryorder = entryorder;
219 this.value = value;
220 this.pqueue = pqueue;
221 }
222
223 public override string ToString()
224 {
225 return String.Format("[{0},{1},{2}]",pqueue,entryorder,value.Entity.LocalId);
226 }
227
228 public int CompareTo(MinHeapItem other)
229 {
230 // I'm assuming that the root part of an SOG is added to the update queue
231 // before the component parts
232 return Comparer<UInt64>.Default.Compare(this.EntryOrder, other.EntryOrder);
233 }
234 }
235#endregion
236
237#region LookupItem
238 private struct LookupItem
239 {
240 internal MinHeap<MinHeapItem> Heap;
241 internal IHandle Handle;
242 }
243#endregion
244 }
245}