aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs1062
1 files changed, 531 insertions, 531 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs
index 5dd1da6..c6da96e 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs
@@ -1,532 +1,532 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright 9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the 12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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 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 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 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. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Threading; 30using System.Threading;
31using System.Timers; 31using System.Timers;
32using libsecondlife; 32using libsecondlife;
33using libsecondlife.Packets; 33using libsecondlife.Packets;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Framework.Statistics; 35using OpenSim.Framework.Statistics;
36using OpenSim.Framework.Statistics.Interfaces; 36using OpenSim.Framework.Statistics.Interfaces;
37using Timer=System.Timers.Timer; 37using Timer=System.Timers.Timer;
38 38
39namespace OpenSim.Region.ClientStack.LindenUDP 39namespace OpenSim.Region.ClientStack.LindenUDP
40{ 40{
41 public class LLPacketQueue : IPullStatsProvider 41 public class LLPacketQueue : IPullStatsProvider
42 { 42 {
43 //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 43 //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
44 44
45 private bool m_enabled = true; 45 private bool m_enabled = true;
46 46
47 private BlockingQueue<LLQueItem> SendQueue; 47 private BlockingQueue<LLQueItem> SendQueue;
48 48
49 private Queue<LLQueItem> IncomingPacketQueue; 49 private Queue<LLQueItem> IncomingPacketQueue;
50 private Queue<LLQueItem> OutgoingPacketQueue; 50 private Queue<LLQueItem> OutgoingPacketQueue;
51 private Queue<LLQueItem> ResendOutgoingPacketQueue; 51 private Queue<LLQueItem> ResendOutgoingPacketQueue;
52 private Queue<LLQueItem> LandOutgoingPacketQueue; 52 private Queue<LLQueItem> LandOutgoingPacketQueue;
53 private Queue<LLQueItem> WindOutgoingPacketQueue; 53 private Queue<LLQueItem> WindOutgoingPacketQueue;
54 private Queue<LLQueItem> CloudOutgoingPacketQueue; 54 private Queue<LLQueItem> CloudOutgoingPacketQueue;
55 private Queue<LLQueItem> TaskOutgoingPacketQueue; 55 private Queue<LLQueItem> TaskOutgoingPacketQueue;
56 private Queue<LLQueItem> TextureOutgoingPacketQueue; 56 private Queue<LLQueItem> TextureOutgoingPacketQueue;
57 private Queue<LLQueItem> AssetOutgoingPacketQueue; 57 private Queue<LLQueItem> AssetOutgoingPacketQueue;
58 58
59 private Dictionary<uint, uint> PendingAcks = new Dictionary<uint, uint>(); 59 private Dictionary<uint, uint> PendingAcks = new Dictionary<uint, uint>();
60 private Dictionary<uint, Packet> NeedAck = new Dictionary<uint, Packet>(); 60 private Dictionary<uint, Packet> NeedAck = new Dictionary<uint, Packet>();
61 61
62 // All throttle times and number of bytes are calculated by dividing by this value 62 // All throttle times and number of bytes are calculated by dividing by this value
63 // This value also determines how many times per throttletimems the timer will run 63 // This value also determines how many times per throttletimems the timer will run
64 // If throttleimems is 1000 ms, then the timer will fire every 1000/7 milliseconds 64 // If throttleimems is 1000 ms, then the timer will fire every 1000/7 milliseconds
65 65
66 private int throttleTimeDivisor = 7; 66 private int throttleTimeDivisor = 7;
67 67
68 private int throttletimems = 1000; 68 private int throttletimems = 1000;
69 69
70 private LLPacketThrottle ResendThrottle; 70 private LLPacketThrottle ResendThrottle;
71 private LLPacketThrottle LandThrottle; 71 private LLPacketThrottle LandThrottle;
72 private LLPacketThrottle WindThrottle; 72 private LLPacketThrottle WindThrottle;
73 private LLPacketThrottle CloudThrottle; 73 private LLPacketThrottle CloudThrottle;
74 private LLPacketThrottle TaskThrottle; 74 private LLPacketThrottle TaskThrottle;
75 private LLPacketThrottle AssetThrottle; 75 private LLPacketThrottle AssetThrottle;
76 private LLPacketThrottle TextureThrottle; 76 private LLPacketThrottle TextureThrottle;
77 private LLPacketThrottle TotalThrottle; 77 private LLPacketThrottle TotalThrottle;
78 78
79 // private long LastThrottle; 79 // private long LastThrottle;
80 // private long ThrottleInterval; 80 // private long ThrottleInterval;
81 private Timer throttleTimer; 81 private Timer throttleTimer;
82 82
83 private LLUUID m_agentId; 83 private LLUUID m_agentId;
84 84
85 public LLPacketQueue(LLUUID agentId) 85 public LLPacketQueue(LLUUID agentId)
86 { 86 {
87 // While working on this, the BlockingQueue had me fooled for a bit. 87 // While working on this, the BlockingQueue had me fooled for a bit.
88 // The Blocking queue causes the thread to stop until there's something 88 // The Blocking queue causes the thread to stop until there's something
89 // in it to process. it's an on-purpose threadlock though because 89 // in it to process. it's an on-purpose threadlock though because
90 // without it, the clientloop will suck up all sim resources. 90 // without it, the clientloop will suck up all sim resources.
91 91
92 SendQueue = new BlockingQueue<LLQueItem>(); 92 SendQueue = new BlockingQueue<LLQueItem>();
93 93
94 IncomingPacketQueue = new Queue<LLQueItem>(); 94 IncomingPacketQueue = new Queue<LLQueItem>();
95 OutgoingPacketQueue = new Queue<LLQueItem>(); 95 OutgoingPacketQueue = new Queue<LLQueItem>();
96 ResendOutgoingPacketQueue = new Queue<LLQueItem>(); 96 ResendOutgoingPacketQueue = new Queue<LLQueItem>();
97 LandOutgoingPacketQueue = new Queue<LLQueItem>(); 97 LandOutgoingPacketQueue = new Queue<LLQueItem>();
98 WindOutgoingPacketQueue = new Queue<LLQueItem>(); 98 WindOutgoingPacketQueue = new Queue<LLQueItem>();
99 CloudOutgoingPacketQueue = new Queue<LLQueItem>(); 99 CloudOutgoingPacketQueue = new Queue<LLQueItem>();
100 TaskOutgoingPacketQueue = new Queue<LLQueItem>(); 100 TaskOutgoingPacketQueue = new Queue<LLQueItem>();
101 TextureOutgoingPacketQueue = new Queue<LLQueItem>(); 101 TextureOutgoingPacketQueue = new Queue<LLQueItem>();
102 AssetOutgoingPacketQueue = new Queue<LLQueItem>(); 102 AssetOutgoingPacketQueue = new Queue<LLQueItem>();
103 103
104 104
105 // Set up the throttle classes (min, max, current) in bytes 105 // Set up the throttle classes (min, max, current) in bytes
106 ResendThrottle = new LLPacketThrottle(5000, 100000, 16000); 106 ResendThrottle = new LLPacketThrottle(5000, 100000, 16000);
107 LandThrottle = new LLPacketThrottle(1000, 100000, 2000); 107 LandThrottle = new LLPacketThrottle(1000, 100000, 2000);
108 WindThrottle = new LLPacketThrottle(1000, 100000, 1000); 108 WindThrottle = new LLPacketThrottle(1000, 100000, 1000);
109 CloudThrottle = new LLPacketThrottle(1000, 100000, 1000); 109 CloudThrottle = new LLPacketThrottle(1000, 100000, 1000);
110 TaskThrottle = new LLPacketThrottle(1000, 800000, 3000); 110 TaskThrottle = new LLPacketThrottle(1000, 800000, 3000);
111 AssetThrottle = new LLPacketThrottle(1000, 800000, 1000); 111 AssetThrottle = new LLPacketThrottle(1000, 800000, 1000);
112 TextureThrottle = new LLPacketThrottle(1000, 800000, 4000); 112 TextureThrottle = new LLPacketThrottle(1000, 800000, 4000);
113 // Total Throttle trumps all 113 // Total Throttle trumps all
114 // Number of bytes allowed to go out per second. (256kbps per client) 114 // Number of bytes allowed to go out per second. (256kbps per client)
115 TotalThrottle = new LLPacketThrottle(0, 1500000, 28000); 115 TotalThrottle = new LLPacketThrottle(0, 1500000, 28000);
116 116
117 throttleTimer = new Timer((int) (throttletimems/throttleTimeDivisor)); 117 throttleTimer = new Timer((int) (throttletimems/throttleTimeDivisor));
118 throttleTimer.Elapsed += new ElapsedEventHandler(ThrottleTimerElapsed); 118 throttleTimer.Elapsed += new ElapsedEventHandler(ThrottleTimerElapsed);
119 throttleTimer.Start(); 119 throttleTimer.Start();
120 120
121 // TIMERS needed for this 121 // TIMERS needed for this
122 // LastThrottle = DateTime.Now.Ticks; 122 // LastThrottle = DateTime.Now.Ticks;
123 // ThrottleInterval = (long)(throttletimems/throttleTimeDivisor); 123 // ThrottleInterval = (long)(throttletimems/throttleTimeDivisor);
124 124
125 m_agentId = agentId; 125 m_agentId = agentId;
126 126
127 if (StatsManager.SimExtraStats != null) 127 if (StatsManager.SimExtraStats != null)
128 { 128 {
129 StatsManager.SimExtraStats.RegisterPacketQueueStatsProvider(m_agentId, this); 129 StatsManager.SimExtraStats.RegisterPacketQueueStatsProvider(m_agentId, this);
130 } 130 }
131 } 131 }
132 132
133 /* STANDARD QUEUE MANIPULATION INTERFACES */ 133 /* STANDARD QUEUE MANIPULATION INTERFACES */
134 134
135 135
136 public void Enqueue(LLQueItem item) 136 public void Enqueue(LLQueItem item)
137 { 137 {
138 if (!m_enabled) 138 if (!m_enabled)
139 { 139 {
140 return; 140 return;
141 } 141 }
142 // We could micro lock, but that will tend to actually 142 // We could micro lock, but that will tend to actually
143 // probably be worse than just synchronizing on SendQueue 143 // probably be worse than just synchronizing on SendQueue
144 144
145 if (item == null) 145 if (item == null)
146 { 146 {
147 SendQueue.Enqueue(item); 147 SendQueue.Enqueue(item);
148 return; 148 return;
149 } 149 }
150 150
151 lock (this) { 151 lock (this) {
152 switch (item.throttleType) 152 switch (item.throttleType)
153 { 153 {
154 case ThrottleOutPacketType.Resend: 154 case ThrottleOutPacketType.Resend:
155 ThrottleCheck(ref ResendThrottle, ref ResendOutgoingPacketQueue, item); 155 ThrottleCheck(ref ResendThrottle, ref ResendOutgoingPacketQueue, item);
156 break; 156 break;
157 case ThrottleOutPacketType.Texture: 157 case ThrottleOutPacketType.Texture:
158 ThrottleCheck(ref TextureThrottle, ref TextureOutgoingPacketQueue, item); 158 ThrottleCheck(ref TextureThrottle, ref TextureOutgoingPacketQueue, item);
159 break; 159 break;
160 case ThrottleOutPacketType.Task: 160 case ThrottleOutPacketType.Task:
161 ThrottleCheck(ref TaskThrottle, ref TaskOutgoingPacketQueue, item); 161 ThrottleCheck(ref TaskThrottle, ref TaskOutgoingPacketQueue, item);
162 break; 162 break;
163 case ThrottleOutPacketType.Land: 163 case ThrottleOutPacketType.Land:
164 ThrottleCheck(ref LandThrottle, ref LandOutgoingPacketQueue, item); 164 ThrottleCheck(ref LandThrottle, ref LandOutgoingPacketQueue, item);
165 break; 165 break;
166 case ThrottleOutPacketType.Asset: 166 case ThrottleOutPacketType.Asset:
167 ThrottleCheck(ref AssetThrottle, ref AssetOutgoingPacketQueue, item); 167 ThrottleCheck(ref AssetThrottle, ref AssetOutgoingPacketQueue, item);
168 break; 168 break;
169 case ThrottleOutPacketType.Cloud: 169 case ThrottleOutPacketType.Cloud:
170 ThrottleCheck(ref CloudThrottle, ref CloudOutgoingPacketQueue, item); 170 ThrottleCheck(ref CloudThrottle, ref CloudOutgoingPacketQueue, item);
171 break; 171 break;
172 case ThrottleOutPacketType.Wind: 172 case ThrottleOutPacketType.Wind:
173 ThrottleCheck(ref WindThrottle, ref WindOutgoingPacketQueue, item); 173 ThrottleCheck(ref WindThrottle, ref WindOutgoingPacketQueue, item);
174 break; 174 break;
175 175
176 default: 176 default:
177 // Acknowledgements and other such stuff should go directly to the blocking Queue 177 // Acknowledgements and other such stuff should go directly to the blocking Queue
178 // Throttling them may and likely 'will' be problematic 178 // Throttling them may and likely 'will' be problematic
179 SendQueue.Enqueue(item); 179 SendQueue.Enqueue(item);
180 break; 180 break;
181 } 181 }
182 } 182 }
183 } 183 }
184 184
185 public LLQueItem Dequeue() 185 public LLQueItem Dequeue()
186 { 186 {
187 return SendQueue.Dequeue(); 187 return SendQueue.Dequeue();
188 } 188 }
189 189
190 public void Flush() 190 public void Flush()
191 { 191 {
192 lock (this) 192 lock (this)
193 { 193 {
194 while (PacketsWaiting()) 194 while (PacketsWaiting())
195 { 195 {
196 //Now comes the fun part.. we dump all our elements into m_packetQueue that we've saved up. 196 //Now comes the fun part.. we dump all our elements into m_packetQueue that we've saved up.
197 if (ResendOutgoingPacketQueue.Count > 0) 197 if (ResendOutgoingPacketQueue.Count > 0)
198 { 198 {
199 SendQueue.Enqueue(ResendOutgoingPacketQueue.Dequeue()); 199 SendQueue.Enqueue(ResendOutgoingPacketQueue.Dequeue());
200 } 200 }
201 if (LandOutgoingPacketQueue.Count > 0) 201 if (LandOutgoingPacketQueue.Count > 0)
202 { 202 {
203 SendQueue.Enqueue(LandOutgoingPacketQueue.Dequeue()); 203 SendQueue.Enqueue(LandOutgoingPacketQueue.Dequeue());
204 } 204 }
205 if (WindOutgoingPacketQueue.Count > 0) 205 if (WindOutgoingPacketQueue.Count > 0)
206 { 206 {
207 SendQueue.Enqueue(WindOutgoingPacketQueue.Dequeue()); 207 SendQueue.Enqueue(WindOutgoingPacketQueue.Dequeue());
208 } 208 }
209 if (CloudOutgoingPacketQueue.Count > 0) 209 if (CloudOutgoingPacketQueue.Count > 0)
210 { 210 {
211 SendQueue.Enqueue(CloudOutgoingPacketQueue.Dequeue()); 211 SendQueue.Enqueue(CloudOutgoingPacketQueue.Dequeue());
212 } 212 }
213 if (TaskOutgoingPacketQueue.Count > 0) 213 if (TaskOutgoingPacketQueue.Count > 0)
214 { 214 {
215 SendQueue.Enqueue(TaskOutgoingPacketQueue.Dequeue()); 215 SendQueue.Enqueue(TaskOutgoingPacketQueue.Dequeue());
216 } 216 }
217 if (TextureOutgoingPacketQueue.Count > 0) 217 if (TextureOutgoingPacketQueue.Count > 0)
218 { 218 {
219 SendQueue.Enqueue(TextureOutgoingPacketQueue.Dequeue()); 219 SendQueue.Enqueue(TextureOutgoingPacketQueue.Dequeue());
220 } 220 }
221 if (AssetOutgoingPacketQueue.Count > 0) 221 if (AssetOutgoingPacketQueue.Count > 0)
222 { 222 {
223 SendQueue.Enqueue(AssetOutgoingPacketQueue.Dequeue()); 223 SendQueue.Enqueue(AssetOutgoingPacketQueue.Dequeue());
224 } 224 }
225 } 225 }
226 // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets"); 226 // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets");
227 } 227 }
228 } 228 }
229 229
230 public void Close() 230 public void Close()
231 { 231 {
232 Flush(); 232 Flush();
233 233
234 m_enabled = false; 234 m_enabled = false;
235 throttleTimer.Stop(); 235 throttleTimer.Stop();
236 236
237 if (StatsManager.SimExtraStats != null) 237 if (StatsManager.SimExtraStats != null)
238 { 238 {
239 StatsManager.SimExtraStats.DeregisterPacketQueueStatsProvider(m_agentId); 239 StatsManager.SimExtraStats.DeregisterPacketQueueStatsProvider(m_agentId);
240 } 240 }
241 } 241 }
242 242
243 private void ResetCounters() 243 private void ResetCounters()
244 { 244 {
245 ResendThrottle.Reset(); 245 ResendThrottle.Reset();
246 LandThrottle.Reset(); 246 LandThrottle.Reset();
247 WindThrottle.Reset(); 247 WindThrottle.Reset();
248 CloudThrottle.Reset(); 248 CloudThrottle.Reset();
249 TaskThrottle.Reset(); 249 TaskThrottle.Reset();
250 AssetThrottle.Reset(); 250 AssetThrottle.Reset();
251 TextureThrottle.Reset(); 251 TextureThrottle.Reset();
252 TotalThrottle.Reset(); 252 TotalThrottle.Reset();
253 } 253 }
254 254
255 private bool PacketsWaiting() 255 private bool PacketsWaiting()
256 { 256 {
257 return (ResendOutgoingPacketQueue.Count > 0 || 257 return (ResendOutgoingPacketQueue.Count > 0 ||
258 LandOutgoingPacketQueue.Count > 0 || 258 LandOutgoingPacketQueue.Count > 0 ||
259 WindOutgoingPacketQueue.Count > 0 || 259 WindOutgoingPacketQueue.Count > 0 ||
260 CloudOutgoingPacketQueue.Count > 0 || 260 CloudOutgoingPacketQueue.Count > 0 ||
261 TaskOutgoingPacketQueue.Count > 0 || 261 TaskOutgoingPacketQueue.Count > 0 ||
262 AssetOutgoingPacketQueue.Count > 0 || 262 AssetOutgoingPacketQueue.Count > 0 ||
263 TextureOutgoingPacketQueue.Count > 0); 263 TextureOutgoingPacketQueue.Count > 0);
264 } 264 }
265 265
266 public void ProcessThrottle() 266 public void ProcessThrottle()
267 { 267 {
268 // I was considering this.. Will an event fire if the thread it's on is blocked? 268 // I was considering this.. Will an event fire if the thread it's on is blocked?
269 269
270 // Then I figured out.. it doesn't really matter.. because this thread won't be blocked for long 270 // Then I figured out.. it doesn't really matter.. because this thread won't be blocked for long
271 // The General overhead of the UDP protocol gets sent to the queue un-throttled by this 271 // The General overhead of the UDP protocol gets sent to the queue un-throttled by this
272 // so This'll pick up about around the right time. 272 // so This'll pick up about around the right time.
273 273
274 int MaxThrottleLoops = 4550; // 50*7 packets can be dequeued at once. 274 int MaxThrottleLoops = 4550; // 50*7 packets can be dequeued at once.
275 int throttleLoops = 0; 275 int throttleLoops = 0;
276 276
277 // We're going to dequeue all of the saved up packets until 277 // We're going to dequeue all of the saved up packets until
278 // we've hit the throttle limit or there's no more packets to send 278 // we've hit the throttle limit or there's no more packets to send
279 lock (this) 279 lock (this)
280 { 280 {
281 ResetCounters(); 281 ResetCounters();
282 // m_log.Info("[THROTTLE]: Entering Throttle"); 282 // m_log.Info("[THROTTLE]: Entering Throttle");
283 while (TotalThrottle.UnderLimit() && PacketsWaiting() && 283 while (TotalThrottle.UnderLimit() && PacketsWaiting() &&
284 (throttleLoops <= MaxThrottleLoops)) 284 (throttleLoops <= MaxThrottleLoops))
285 { 285 {
286 throttleLoops++; 286 throttleLoops++;
287 //Now comes the fun part.. we dump all our elements into m_packetQueue that we've saved up. 287 //Now comes the fun part.. we dump all our elements into m_packetQueue that we've saved up.
288 if (ResendThrottle.UnderLimit() && ResendOutgoingPacketQueue.Count > 0) 288 if (ResendThrottle.UnderLimit() && ResendOutgoingPacketQueue.Count > 0)
289 { 289 {
290 LLQueItem qpack = ResendOutgoingPacketQueue.Dequeue(); 290 LLQueItem qpack = ResendOutgoingPacketQueue.Dequeue();
291 291
292 SendQueue.Enqueue(qpack); 292 SendQueue.Enqueue(qpack);
293 TotalThrottle.Add(qpack.Packet.ToBytes().Length); 293 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
294 ResendThrottle.Add(qpack.Packet.ToBytes().Length); 294 ResendThrottle.Add(qpack.Packet.ToBytes().Length);
295 } 295 }
296 if (LandThrottle.UnderLimit() && LandOutgoingPacketQueue.Count > 0) 296 if (LandThrottle.UnderLimit() && LandOutgoingPacketQueue.Count > 0)
297 { 297 {
298 LLQueItem qpack = LandOutgoingPacketQueue.Dequeue(); 298 LLQueItem qpack = LandOutgoingPacketQueue.Dequeue();
299 299
300 SendQueue.Enqueue(qpack); 300 SendQueue.Enqueue(qpack);
301 TotalThrottle.Add(qpack.Packet.ToBytes().Length); 301 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
302 LandThrottle.Add(qpack.Packet.ToBytes().Length); 302 LandThrottle.Add(qpack.Packet.ToBytes().Length);
303 } 303 }
304 if (WindThrottle.UnderLimit() && WindOutgoingPacketQueue.Count > 0) 304 if (WindThrottle.UnderLimit() && WindOutgoingPacketQueue.Count > 0)
305 { 305 {
306 LLQueItem qpack = WindOutgoingPacketQueue.Dequeue(); 306 LLQueItem qpack = WindOutgoingPacketQueue.Dequeue();
307 307
308 SendQueue.Enqueue(qpack); 308 SendQueue.Enqueue(qpack);
309 TotalThrottle.Add(qpack.Packet.ToBytes().Length); 309 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
310 WindThrottle.Add(qpack.Packet.ToBytes().Length); 310 WindThrottle.Add(qpack.Packet.ToBytes().Length);
311 } 311 }
312 if (CloudThrottle.UnderLimit() && CloudOutgoingPacketQueue.Count > 0) 312 if (CloudThrottle.UnderLimit() && CloudOutgoingPacketQueue.Count > 0)
313 { 313 {
314 LLQueItem qpack = CloudOutgoingPacketQueue.Dequeue(); 314 LLQueItem qpack = CloudOutgoingPacketQueue.Dequeue();
315 315
316 SendQueue.Enqueue(qpack); 316 SendQueue.Enqueue(qpack);
317 TotalThrottle.Add(qpack.Packet.ToBytes().Length); 317 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
318 CloudThrottle.Add(qpack.Packet.ToBytes().Length); 318 CloudThrottle.Add(qpack.Packet.ToBytes().Length);
319 } 319 }
320 if (TaskThrottle.UnderLimit() && TaskOutgoingPacketQueue.Count > 0) 320 if (TaskThrottle.UnderLimit() && TaskOutgoingPacketQueue.Count > 0)
321 { 321 {
322 LLQueItem qpack = TaskOutgoingPacketQueue.Dequeue(); 322 LLQueItem qpack = TaskOutgoingPacketQueue.Dequeue();
323 323
324 SendQueue.Enqueue(qpack); 324 SendQueue.Enqueue(qpack);
325 TotalThrottle.Add(qpack.Packet.ToBytes().Length); 325 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
326 TaskThrottle.Add(qpack.Packet.ToBytes().Length); 326 TaskThrottle.Add(qpack.Packet.ToBytes().Length);
327 } 327 }
328 if (TextureThrottle.UnderLimit() && TextureOutgoingPacketQueue.Count > 0) 328 if (TextureThrottle.UnderLimit() && TextureOutgoingPacketQueue.Count > 0)
329 { 329 {
330 LLQueItem qpack = TextureOutgoingPacketQueue.Dequeue(); 330 LLQueItem qpack = TextureOutgoingPacketQueue.Dequeue();
331 331
332 SendQueue.Enqueue(qpack); 332 SendQueue.Enqueue(qpack);
333 TotalThrottle.Add(qpack.Packet.ToBytes().Length); 333 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
334 TextureThrottle.Add(qpack.Packet.ToBytes().Length); 334 TextureThrottle.Add(qpack.Packet.ToBytes().Length);
335 } 335 }
336 if (AssetThrottle.UnderLimit() && AssetOutgoingPacketQueue.Count > 0) 336 if (AssetThrottle.UnderLimit() && AssetOutgoingPacketQueue.Count > 0)
337 { 337 {
338 LLQueItem qpack = AssetOutgoingPacketQueue.Dequeue(); 338 LLQueItem qpack = AssetOutgoingPacketQueue.Dequeue();
339 339
340 SendQueue.Enqueue(qpack); 340 SendQueue.Enqueue(qpack);
341 TotalThrottle.Add(qpack.Packet.ToBytes().Length); 341 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
342 AssetThrottle.Add(qpack.Packet.ToBytes().Length); 342 AssetThrottle.Add(qpack.Packet.ToBytes().Length);
343 } 343 }
344 } 344 }
345 // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets"); 345 // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets");
346 } 346 }
347 } 347 }
348 348
349 private void ThrottleTimerElapsed(object sender, ElapsedEventArgs e) 349 private void ThrottleTimerElapsed(object sender, ElapsedEventArgs e)
350 { 350 {
351 // just to change the signature, and that ProcessThrottle 351 // just to change the signature, and that ProcessThrottle
352 // will be used elsewhere possibly 352 // will be used elsewhere possibly
353 ProcessThrottle(); 353 ProcessThrottle();
354 } 354 }
355 355
356 private void ThrottleCheck(ref LLPacketThrottle throttle, ref Queue<LLQueItem> q, LLQueItem item) 356 private void ThrottleCheck(ref LLPacketThrottle throttle, ref Queue<LLQueItem> q, LLQueItem item)
357 { 357 {
358 // The idea.. is if the packet throttle queues are empty 358 // The idea.. is if the packet throttle queues are empty
359 // and the client is under throttle for the type. Queue 359 // and the client is under throttle for the type. Queue
360 // it up directly. This basically short cuts having to 360 // it up directly. This basically short cuts having to
361 // wait for the timer to fire to put things into the 361 // wait for the timer to fire to put things into the
362 // output queue 362 // output queue
363 363
364 if ((q.Count == 0) && (throttle.UnderLimit())) 364 if ((q.Count == 0) && (throttle.UnderLimit()))
365 { 365 {
366 Monitor.Enter(this); 366 Monitor.Enter(this);
367 throttle.Add(item.Packet.ToBytes().Length); 367 throttle.Add(item.Packet.ToBytes().Length);
368 TotalThrottle.Add(item.Packet.ToBytes().Length); 368 TotalThrottle.Add(item.Packet.ToBytes().Length);
369 SendQueue.Enqueue(item); 369 SendQueue.Enqueue(item);
370 Monitor.Pulse(this); 370 Monitor.Pulse(this);
371 Monitor.Exit(this); 371 Monitor.Exit(this);
372 } 372 }
373 else 373 else
374 { 374 {
375 q.Enqueue(item); 375 q.Enqueue(item);
376 } 376 }
377 } 377 }
378 378
379 379
380 private static int ScaleThrottle(int value, int curmax, int newmax) 380 private static int ScaleThrottle(int value, int curmax, int newmax)
381 { 381 {
382 return (value / curmax) * newmax; 382 return (value / curmax) * newmax;
383 } 383 }
384 384
385 public byte[] GetThrottlesPacked(float multiplier) 385 public byte[] GetThrottlesPacked(float multiplier)
386 { 386 {
387 int singlefloat = 4; 387 int singlefloat = 4;
388 float tResend = ResendThrottle.Throttle*multiplier; 388 float tResend = ResendThrottle.Throttle*multiplier;
389 float tLand = LandThrottle.Throttle*multiplier; 389 float tLand = LandThrottle.Throttle*multiplier;
390 float tWind = WindThrottle.Throttle*multiplier; 390 float tWind = WindThrottle.Throttle*multiplier;
391 float tCloud = CloudThrottle.Throttle*multiplier; 391 float tCloud = CloudThrottle.Throttle*multiplier;
392 float tTask = TaskThrottle.Throttle*multiplier; 392 float tTask = TaskThrottle.Throttle*multiplier;
393 float tTexture = TextureThrottle.Throttle*multiplier; 393 float tTexture = TextureThrottle.Throttle*multiplier;
394 float tAsset = AssetThrottle.Throttle*multiplier; 394 float tAsset = AssetThrottle.Throttle*multiplier;
395 395
396 byte[] throttles = new byte[singlefloat*7]; 396 byte[] throttles = new byte[singlefloat*7];
397 int i = 0; 397 int i = 0;
398 Buffer.BlockCopy(BitConverter.GetBytes(tResend), 0, throttles, singlefloat*i, singlefloat); 398 Buffer.BlockCopy(BitConverter.GetBytes(tResend), 0, throttles, singlefloat*i, singlefloat);
399 i++; 399 i++;
400 Buffer.BlockCopy(BitConverter.GetBytes(tLand), 0, throttles, singlefloat*i, singlefloat); 400 Buffer.BlockCopy(BitConverter.GetBytes(tLand), 0, throttles, singlefloat*i, singlefloat);
401 i++; 401 i++;
402 Buffer.BlockCopy(BitConverter.GetBytes(tWind), 0, throttles, singlefloat*i, singlefloat); 402 Buffer.BlockCopy(BitConverter.GetBytes(tWind), 0, throttles, singlefloat*i, singlefloat);
403 i++; 403 i++;
404 Buffer.BlockCopy(BitConverter.GetBytes(tCloud), 0, throttles, singlefloat*i, singlefloat); 404 Buffer.BlockCopy(BitConverter.GetBytes(tCloud), 0, throttles, singlefloat*i, singlefloat);
405 i++; 405 i++;
406 Buffer.BlockCopy(BitConverter.GetBytes(tTask), 0, throttles, singlefloat*i, singlefloat); 406 Buffer.BlockCopy(BitConverter.GetBytes(tTask), 0, throttles, singlefloat*i, singlefloat);
407 i++; 407 i++;
408 Buffer.BlockCopy(BitConverter.GetBytes(tTexture), 0, throttles, singlefloat*i, singlefloat); 408 Buffer.BlockCopy(BitConverter.GetBytes(tTexture), 0, throttles, singlefloat*i, singlefloat);
409 i++; 409 i++;
410 Buffer.BlockCopy(BitConverter.GetBytes(tAsset), 0, throttles, singlefloat*i, singlefloat); 410 Buffer.BlockCopy(BitConverter.GetBytes(tAsset), 0, throttles, singlefloat*i, singlefloat);
411 411
412 return throttles; 412 return throttles;
413 } 413 }
414 414
415 public void SetThrottleFromClient(byte[] throttle) 415 public void SetThrottleFromClient(byte[] throttle)
416 { 416 {
417 int tResend = -1; 417 int tResend = -1;
418 int tLand = -1; 418 int tLand = -1;
419 int tWind = -1; 419 int tWind = -1;
420 int tCloud = -1; 420 int tCloud = -1;
421 int tTask = -1; 421 int tTask = -1;
422 int tTexture = -1; 422 int tTexture = -1;
423 int tAsset = -1; 423 int tAsset = -1;
424 int tall = -1; 424 int tall = -1;
425 int singlefloat = 4; 425 int singlefloat = 4;
426 426
427 //Agent Throttle Block contains 7 single floatingpoint values. 427 //Agent Throttle Block contains 7 single floatingpoint values.
428 int j = 0; 428 int j = 0;
429 429
430 // Some Systems may be big endian... 430 // Some Systems may be big endian...
431 // it might be smart to do this check more often... 431 // it might be smart to do this check more often...
432 if (!BitConverter.IsLittleEndian) 432 if (!BitConverter.IsLittleEndian)
433 for (int i = 0; i < 7; i++) 433 for (int i = 0; i < 7; i++)
434 Array.Reverse(throttle, j + i*singlefloat, singlefloat); 434 Array.Reverse(throttle, j + i*singlefloat, singlefloat);
435 435
436 // values gotten from libsecondlife.org/wiki/Throttle. Thanks MW_ 436 // values gotten from libsecondlife.org/wiki/Throttle. Thanks MW_
437 // bytes 437 // bytes
438 // Convert to integer, since.. the full fp space isn't used. 438 // Convert to integer, since.. the full fp space isn't used.
439 tResend = (int) BitConverter.ToSingle(throttle, j); 439 tResend = (int) BitConverter.ToSingle(throttle, j);
440 j += singlefloat; 440 j += singlefloat;
441 tLand = (int) BitConverter.ToSingle(throttle, j); 441 tLand = (int) BitConverter.ToSingle(throttle, j);
442 j += singlefloat; 442 j += singlefloat;
443 tWind = (int) BitConverter.ToSingle(throttle, j); 443 tWind = (int) BitConverter.ToSingle(throttle, j);
444 j += singlefloat; 444 j += singlefloat;
445 tCloud = (int) BitConverter.ToSingle(throttle, j); 445 tCloud = (int) BitConverter.ToSingle(throttle, j);
446 j += singlefloat; 446 j += singlefloat;
447 tTask = (int) BitConverter.ToSingle(throttle, j); 447 tTask = (int) BitConverter.ToSingle(throttle, j);
448 j += singlefloat; 448 j += singlefloat;
449 tTexture = (int) BitConverter.ToSingle(throttle, j); 449 tTexture = (int) BitConverter.ToSingle(throttle, j);
450 j += singlefloat; 450 j += singlefloat;
451 tAsset = (int) BitConverter.ToSingle(throttle, j); 451 tAsset = (int) BitConverter.ToSingle(throttle, j);
452 452
453 tall = tResend + tLand + tWind + tCloud + tTask + tTexture + tAsset; 453 tall = tResend + tLand + tWind + tCloud + tTask + tTexture + tAsset;
454 /* 454 /*
455 m_log.Info("[CLIENT]: Client AgentThrottle - Got throttle:resendbytes=" + tResend + 455 m_log.Info("[CLIENT]: Client AgentThrottle - Got throttle:resendbytes=" + tResend +
456 " landbytes=" + tLand + 456 " landbytes=" + tLand +
457 " windbytes=" + tWind + 457 " windbytes=" + tWind +
458 " cloudbytes=" + tCloud + 458 " cloudbytes=" + tCloud +
459 " taskbytes=" + tTask + 459 " taskbytes=" + tTask +
460 " texturebytes=" + tTexture + 460 " texturebytes=" + tTexture +
461 " Assetbytes=" + tAsset + 461 " Assetbytes=" + tAsset +
462 " Allbytes=" + tall); 462 " Allbytes=" + tall);
463 */ 463 */
464 464
465 // Total Sanity 465 // Total Sanity
466 // Make sure that the client sent sane total values. 466 // Make sure that the client sent sane total values.
467 467
468 // If the client didn't send acceptable values.... 468 // If the client didn't send acceptable values....
469 // Scale the clients values down until they are acceptable. 469 // Scale the clients values down until they are acceptable.
470 470
471 if (tall <= TotalThrottle.Max) 471 if (tall <= TotalThrottle.Max)
472 { 472 {
473 ResendThrottle.Throttle = tResend; 473 ResendThrottle.Throttle = tResend;
474 LandThrottle.Throttle = tLand; 474 LandThrottle.Throttle = tLand;
475 WindThrottle.Throttle = tWind; 475 WindThrottle.Throttle = tWind;
476 CloudThrottle.Throttle = tCloud; 476 CloudThrottle.Throttle = tCloud;
477 TaskThrottle.Throttle = tTask; 477 TaskThrottle.Throttle = tTask;
478 TextureThrottle.Throttle = tTexture; 478 TextureThrottle.Throttle = tTexture;
479 AssetThrottle.Throttle = tAsset; 479 AssetThrottle.Throttle = tAsset;
480 TotalThrottle.Throttle = tall; 480 TotalThrottle.Throttle = tall;
481 } 481 }
482 else if (tall < 1) 482 else if (tall < 1)
483 { 483 {
484 // client is stupid, penalize him by minning everything 484 // client is stupid, penalize him by minning everything
485 ResendThrottle.Throttle = ResendThrottle.Min; 485 ResendThrottle.Throttle = ResendThrottle.Min;
486 LandThrottle.Throttle = LandThrottle.Min; 486 LandThrottle.Throttle = LandThrottle.Min;
487 WindThrottle.Throttle = WindThrottle.Min; 487 WindThrottle.Throttle = WindThrottle.Min;
488 CloudThrottle.Throttle = CloudThrottle.Min; 488 CloudThrottle.Throttle = CloudThrottle.Min;
489 TaskThrottle.Throttle = TaskThrottle.Min; 489 TaskThrottle.Throttle = TaskThrottle.Min;
490 TextureThrottle.Throttle = TextureThrottle.Min; 490 TextureThrottle.Throttle = TextureThrottle.Min;
491 AssetThrottle.Throttle = AssetThrottle.Min; 491 AssetThrottle.Throttle = AssetThrottle.Min;
492 TotalThrottle.Throttle = TotalThrottle.Min; 492 TotalThrottle.Throttle = TotalThrottle.Min;
493 } 493 }
494 else 494 else
495 { 495 {
496 // we're over so figure out percentages and use those 496 // we're over so figure out percentages and use those
497 ResendThrottle.Throttle = tResend; 497 ResendThrottle.Throttle = tResend;
498 498
499 LandThrottle.Throttle = ScaleThrottle(tLand, tall, TotalThrottle.Max); 499 LandThrottle.Throttle = ScaleThrottle(tLand, tall, TotalThrottle.Max);
500 WindThrottle.Throttle = ScaleThrottle(tWind, tall, TotalThrottle.Max); 500 WindThrottle.Throttle = ScaleThrottle(tWind, tall, TotalThrottle.Max);
501 CloudThrottle.Throttle = ScaleThrottle(tCloud, tall, TotalThrottle.Max); 501 CloudThrottle.Throttle = ScaleThrottle(tCloud, tall, TotalThrottle.Max);
502 TaskThrottle.Throttle = ScaleThrottle(tTask, tall, TotalThrottle.Max); 502 TaskThrottle.Throttle = ScaleThrottle(tTask, tall, TotalThrottle.Max);
503 TextureThrottle.Throttle = ScaleThrottle(tTexture, tall, TotalThrottle.Max); 503 TextureThrottle.Throttle = ScaleThrottle(tTexture, tall, TotalThrottle.Max);
504 AssetThrottle.Throttle = ScaleThrottle(tAsset, tall, TotalThrottle.Max); 504 AssetThrottle.Throttle = ScaleThrottle(tAsset, tall, TotalThrottle.Max);
505 TotalThrottle.Throttle = TotalThrottle.Max; 505 TotalThrottle.Throttle = TotalThrottle.Max;
506 } 506 }
507 // effectively wiggling the slider causes things reset 507 // effectively wiggling the slider causes things reset
508 ResetCounters(); 508 ResetCounters();
509 } 509 }
510 510
511 // See IPullStatsProvider 511 // See IPullStatsProvider
512 public string GetStats() 512 public string GetStats()
513 { 513 {
514 return string.Format("{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}", 514 return string.Format("{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}",
515 SendQueue.Count(), 515 SendQueue.Count(),
516 IncomingPacketQueue.Count, 516 IncomingPacketQueue.Count,
517 OutgoingPacketQueue.Count, 517 OutgoingPacketQueue.Count,
518 ResendOutgoingPacketQueue.Count, 518 ResendOutgoingPacketQueue.Count,
519 LandOutgoingPacketQueue.Count, 519 LandOutgoingPacketQueue.Count,
520 WindOutgoingPacketQueue.Count, 520 WindOutgoingPacketQueue.Count,
521 CloudOutgoingPacketQueue.Count, 521 CloudOutgoingPacketQueue.Count,
522 TaskOutgoingPacketQueue.Count, 522 TaskOutgoingPacketQueue.Count,
523 TextureOutgoingPacketQueue.Count, 523 TextureOutgoingPacketQueue.Count,
524 AssetOutgoingPacketQueue.Count); 524 AssetOutgoingPacketQueue.Count);
525 } 525 }
526 526
527 public LLQueItem[] GetQueueArray() 527 public LLQueItem[] GetQueueArray()
528 { 528 {
529 return SendQueue.GetQueueArray(); 529 return SendQueue.GetQueueArray();
530 } 530 }
531 } 531 }
532} \ No newline at end of file 532} \ No newline at end of file