aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/PacketQueue.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ClientStack/PacketQueue.cs142
1 files changed, 42 insertions, 100 deletions
diff --git a/OpenSim/Region/ClientStack/PacketQueue.cs b/OpenSim/Region/ClientStack/PacketQueue.cs
index f2d270c..5deede5 100644
--- a/OpenSim/Region/ClientStack/PacketQueue.cs
+++ b/OpenSim/Region/ClientStack/PacketQueue.cs
@@ -44,7 +44,7 @@ namespace OpenSim.Region.ClientStack
44{ 44{
45 public class PacketQueue 45 public class PacketQueue
46 { 46 {
47 private Queue<QueItem> SendQueue; 47 private BlockingQueue<QueItem> SendQueue;
48 48
49 private Queue<QueItem> IncomingPacketQueue; 49 private Queue<QueItem> IncomingPacketQueue;
50 private Queue<QueItem> OutgoingPacketQueue; 50 private Queue<QueItem> OutgoingPacketQueue;
@@ -76,8 +76,9 @@ namespace OpenSim.Region.ClientStack
76 private PacketThrottle TextureThrottle; 76 private PacketThrottle TextureThrottle;
77 private PacketThrottle TotalThrottle; 77 private PacketThrottle TotalThrottle;
78 78
79 private long LastThrottle; 79 // private long LastThrottle;
80 private long ThrottleInterval; 80 // private long ThrottleInterval;
81 private Timer throttleTimer;
81 82
82 public PacketQueue() 83 public PacketQueue()
83 { 84 {
@@ -86,7 +87,7 @@ namespace OpenSim.Region.ClientStack
86 // in it to process. it's an on-purpose threadlock though because 87 // in it to process. it's an on-purpose threadlock though because
87 // without it, the clientloop will suck up all sim resources. 88 // without it, the clientloop will suck up all sim resources.
88 89
89 SendQueue = new Queue<QueItem>(); 90 SendQueue = new BlockingQueue<QueItem>();
90 91
91 IncomingPacketQueue = new Queue<QueItem>(); 92 IncomingPacketQueue = new Queue<QueItem>();
92 OutgoingPacketQueue = new Queue<QueItem>(); 93 OutgoingPacketQueue = new Queue<QueItem>();
@@ -110,10 +111,15 @@ namespace OpenSim.Region.ClientStack
110 // Total Throttle trumps all 111 // Total Throttle trumps all
111 // Number of bytes allowed to go out per second. (256kbps per client) 112 // Number of bytes allowed to go out per second. (256kbps per client)
112 TotalThrottle = new PacketThrottle(0, 162144, 1536000); 113 TotalThrottle = new PacketThrottle(0, 162144, 1536000);
114
115 throttleTimer = new Timer((int)(throttletimems/throttleTimeDivisor));
116 throttleTimer.Elapsed += new ElapsedEventHandler(ThrottleTimerElapsed);
117 throttleTimer.Start();
113 118
114 // TIMERS needed for this 119 // TIMERS needed for this
115 LastThrottle = DateTime.Now.Ticks; 120 // LastThrottle = DateTime.Now.Ticks;
116 ThrottleInterval = (long)(throttletimems/throttleTimeDivisor); 121 // ThrottleInterval = (long)(throttletimems/throttleTimeDivisor);
122
117 } 123 }
118 124
119 /* STANDARD QUEUE MANIPULATION INTERFACES */ 125 /* STANDARD QUEUE MANIPULATION INTERFACES */
@@ -123,7 +129,7 @@ namespace OpenSim.Region.ClientStack
123 { 129 {
124 // We could micro lock, but that will tend to actually 130 // We could micro lock, but that will tend to actually
125 // probably be worse than just synchronizing on SendQueue 131 // probably be worse than just synchronizing on SendQueue
126 lock (SendQueue) { 132 lock (this) {
127 switch (item.throttleType) 133 switch (item.throttleType)
128 { 134 {
129 case ThrottleOutPacketType.Resend: 135 case ThrottleOutPacketType.Resend:
@@ -159,12 +165,14 @@ namespace OpenSim.Region.ClientStack
159 165
160 public QueItem Dequeue() 166 public QueItem Dequeue()
161 { 167 {
162 if (ThrottlingTime()) { 168 return SendQueue.Dequeue();
163 ProcessThrottle(); 169 }
164 } 170
165 lock (SendQueue) { 171 public void Close()
166 return SendQueue.Dequeue(); 172 {
167 } 173 // one last push
174 ProcessThrottle();
175 throttleTimer.Stop();
168 } 176 }
169 177
170 private void ResetCounters() 178 private void ResetCounters()
@@ -192,15 +200,15 @@ namespace OpenSim.Region.ClientStack
192 200
193 // Run through our wait queues and flush out allotted numbers of bytes into the process queue 201 // Run through our wait queues and flush out allotted numbers of bytes into the process queue
194 202
195 private bool ThrottlingTime() 203// private bool ThrottlingTime()
196 { 204// {
197 if(DateTime.Now.Ticks < (LastThrottle + ThrottleInterval)) { 205// if(DateTime.Now.Ticks > (LastThrottle + ThrottleInterval)) {
198 LastThrottle = DateTime.Now.Ticks; 206// LastThrottle = DateTime.Now.Ticks;
199 return true; 207// return true;
200 } else { 208// } else {
201 return false; 209// return false;
202 } 210// }
203 } 211// }
204 212
205 public void ProcessThrottle() 213 public void ProcessThrottle()
206 { 214 {
@@ -216,8 +224,9 @@ namespace OpenSim.Region.ClientStack
216 224
217 // We're going to dequeue all of the saved up packets until 225 // We're going to dequeue all of the saved up packets until
218 // we've hit the throttle limit or there's no more packets to send 226 // we've hit the throttle limit or there's no more packets to send
219 lock (SendQueue) { 227 lock (this) {
220 ResetCounters(); 228 ResetCounters();
229 // MainLog.Instance.Verbose("THROTTLE", "Entering Throttle");
221 while (TotalThrottle.UnderLimit() && PacketsWaiting() && 230 while (TotalThrottle.UnderLimit() && PacketsWaiting() &&
222 (throttleLoops <= MaxThrottleLoops)) 231 (throttleLoops <= MaxThrottleLoops))
223 { 232 {
@@ -280,86 +289,16 @@ namespace OpenSim.Region.ClientStack
280 AssetThrottle.Add(qpack.Packet.ToBytes().Length); 289 AssetThrottle.Add(qpack.Packet.ToBytes().Length);
281 } 290 }
282 } 291 }
292 // MainLog.Instance.Verbose("THROTTLE", "Processed " + throttleLoops + " packets");
293
283 } 294 }
284 } 295 }
285 296
286 private void throttleTimer_Elapsed(object sender, ElapsedEventArgs e) 297 private void ThrottleTimerElapsed(object sender, ElapsedEventArgs e)
287 { 298 {
288 ResetCounters(); 299 // just to change the signature, and that ProcessThrottle
289 300 // will be used elsewhere possibly
290 // I was considering this.. Will an event fire if the thread it's on is blocked? 301 ProcessThrottle();
291
292 // Then I figured out.. it doesn't really matter.. because this thread won't be blocked for long
293 // The General overhead of the UDP protocol gets sent to the queue un-throttled by this
294 // so This'll pick up about around the right time.
295
296 int MaxThrottleLoops = 4550; // 50*7 packets can be dequeued at once.
297 int throttleLoops = 0;
298
299 // We're going to dequeue all of the saved up packets until
300 // we've hit the throttle limit or there's no more packets to send
301 while (TotalThrottle.UnderLimit() && PacketsWaiting() &&
302 (throttleLoops <= MaxThrottleLoops))
303 {
304 throttleLoops++;
305 //Now comes the fun part.. we dump all our elements into PacketQueue that we've saved up.
306 if (ResendThrottle.UnderLimit() && ResendOutgoingPacketQueue.Count > 0)
307 {
308 QueItem qpack = ResendOutgoingPacketQueue.Dequeue();
309
310 SendQueue.Enqueue(qpack);
311 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
312 ResendThrottle.Add(qpack.Packet.ToBytes().Length);
313 }
314 if (LandThrottle.UnderLimit() && LandOutgoingPacketQueue.Count > 0)
315 {
316 QueItem qpack = LandOutgoingPacketQueue.Dequeue();
317
318 SendQueue.Enqueue(qpack);
319 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
320 LandThrottle.Add(qpack.Packet.ToBytes().Length);
321 }
322 if (WindThrottle.UnderLimit() && WindOutgoingPacketQueue.Count > 0)
323 {
324 QueItem qpack = WindOutgoingPacketQueue.Dequeue();
325
326 SendQueue.Enqueue(qpack);
327 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
328 WindThrottle.Add(qpack.Packet.ToBytes().Length);
329 }
330 if (CloudThrottle.UnderLimit() && CloudOutgoingPacketQueue.Count > 0)
331 {
332 QueItem qpack = CloudOutgoingPacketQueue.Dequeue();
333
334 SendQueue.Enqueue(qpack);
335 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
336 CloudThrottle.Add(qpack.Packet.ToBytes().Length);
337 }
338 if (TaskThrottle.UnderLimit() && TaskOutgoingPacketQueue.Count > 0)
339 {
340 QueItem qpack = TaskOutgoingPacketQueue.Dequeue();
341
342 SendQueue.Enqueue(qpack);
343 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
344 TaskThrottle.Add(qpack.Packet.ToBytes().Length);
345 }
346 if (TextureThrottle.UnderLimit() && TextureOutgoingPacketQueue.Count > 0)
347 {
348 QueItem qpack = TextureOutgoingPacketQueue.Dequeue();
349
350 SendQueue.Enqueue(qpack);
351 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
352 TextureThrottle.Add(qpack.Packet.ToBytes().Length);
353 }
354 if (AssetThrottle.UnderLimit() && AssetOutgoingPacketQueue.Count > 0)
355 {
356 QueItem qpack = AssetOutgoingPacketQueue.Dequeue();
357
358 SendQueue.Enqueue(qpack);
359 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
360 AssetThrottle.Add(qpack.Packet.ToBytes().Length);
361 }
362 }
363 } 302 }
364 303
365 private void ThrottleCheck(ref PacketThrottle throttle, ref Queue<QueItem> q, QueItem item) 304 private void ThrottleCheck(ref PacketThrottle throttle, ref Queue<QueItem> q, QueItem item)
@@ -372,9 +311,12 @@ namespace OpenSim.Region.ClientStack
372 311
373 if((q.Count == 0) && (throttle.UnderLimit())) 312 if((q.Count == 0) && (throttle.UnderLimit()))
374 { 313 {
314 Monitor.Enter(this);
375 throttle.Add(item.Packet.ToBytes().Length); 315 throttle.Add(item.Packet.ToBytes().Length);
376 TotalThrottle.Add(item.Packet.ToBytes().Length); 316 TotalThrottle.Add(item.Packet.ToBytes().Length);
377 SendQueue.Enqueue(item); 317 SendQueue.Enqueue(item);
318 Monitor.Pulse(this);
319 Monitor.Exit(this);
378 } 320 }
379 else 321 else
380 { 322 {