aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/ClientView.cs
diff options
context:
space:
mode:
authorTeravus Ovares2007-11-22 19:01:53 +0000
committerTeravus Ovares2007-11-22 19:01:53 +0000
commit999eec603ea62056f599761b90c7a0510336cdd9 (patch)
tree436e7a97ec06ab22b2378d24c5feb5296cfd7a6a /OpenSim/Region/ClientStack/ClientView.cs
parent* removed erroneous comments (diff)
downloadopensim-SC-999eec603ea62056f599761b90c7a0510336cdd9.zip
opensim-SC-999eec603ea62056f599761b90c7a0510336cdd9.tar.gz
opensim-SC-999eec603ea62056f599761b90c7a0510336cdd9.tar.bz2
opensim-SC-999eec603ea62056f599761b90c7a0510336cdd9.tar.xz
Created a client driven packet throttler. The sim now respects the client's network throttle settings but does sanity checks to avoid too little(nothing gets sent) or too much(the sim crashes) data.
* Consider this experimental.. however, it looks very promising.
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ClientStack/ClientView.cs158
1 files changed, 153 insertions, 5 deletions
diff --git a/OpenSim/Region/ClientStack/ClientView.cs b/OpenSim/Region/ClientStack/ClientView.cs
index 10f880b..411883b 100644
--- a/OpenSim/Region/ClientStack/ClientView.cs
+++ b/OpenSim/Region/ClientStack/ClientView.cs
@@ -87,11 +87,53 @@ namespace OpenSim.Region.ClientStack
87 private int probesWithNoIngressPackets = 0; 87 private int probesWithNoIngressPackets = 0;
88 private int lastPacketsReceived = 0; 88 private int lastPacketsReceived = 0;
89 89
90 90 // 1536000
91 private int throttleOutbound = 262144; // Number of bytes allowed to go out per second. (256kbps per client) 91 private int throttleOutboundMax = 1536000; // Number of bytes allowed to go out per second. (256kbps per client)
92 // TODO: Make this variable. Lower throttle on un-ack. Raise over time? 92 // TODO: Make this variable. Lower throttle on un-ack. Raise over time?
93 private int throttleSentPeriod = 0; // Number of bytes sent this period 93 private int throttleSentPeriod = 0; // Number of bytes sent this period
94 94
95 private int throttleOutbound = 162144; // Number of bytes allowed to go out per second. (256kbps per client)
96 // TODO: Make this variable. Lower throttle on un-ack. Raise over time
97
98 // All throttle times and number of bytes are calculated by dividing by this value
99 private int throttleTimeDivisor = 5;
100
101 private int throttletimems = 1000;
102
103 // Maximum -per type- throttle
104 private int ResendthrottleMAX = 100000;
105 private int LandthrottleMax = 100000;
106 private int WindthrottleMax = 100000;
107 private int CloudthrottleMax = 100000;
108 private int TaskthrottleMax = 800000;
109 private int AssetthrottleMax = 800000;
110 private int TexturethrottleMax = 800000;
111
112 // Minimum -per type- throttle
113 private int ResendthrottleMin = 5000; // setting resendmin to 0 results in mostly dropped packets
114 private int LandthrottleMin = 1000;
115 private int WindthrottleMin = 1000;
116 private int CloudthrottleMin = 1000;
117 private int TaskthrottleMin = 1000;
118 private int AssetthrottleMin = 1000;
119 private int TexturethrottleMin = 1000;
120
121 // Sim default per-client settings.
122 private int ResendthrottleOutbound = 50000;
123 private int ResendthrottleSentPeriod = 0;
124 private int LandthrottleOutbound = 100000;
125 private int LandthrottleSentPeriod = 0;
126 private int WindthrottleOutbound = 10000;
127 private int WindthrottleSentPeriod = 0;
128 private int CloudthrottleOutbound = 5000;
129 private int CloudthrottleSentPeriod = 0;
130 private int TaskthrottleOutbound = 100000;
131 private int TaskthrottleSentPeriod = 0;
132 private int AssetthrottleOutbound = 80000;
133 private int AssetthrottleSentPeriod = 0;
134 private int TexturethrottleOutbound = 100000;
135 private int TexturethrottleSentPeriod = 0;
136
95 private Timer throttleTimer; 137 private Timer throttleTimer;
96 138
97 public ClientView(EndPoint remoteEP, UseCircuitCodePacket initialcirpack, ClientManager clientManager, 139 public ClientView(EndPoint remoteEP, UseCircuitCodePacket initialcirpack, ClientManager clientManager,
@@ -114,14 +156,31 @@ namespace OpenSim.Region.ClientStack
114 156
115 startpos = m_authenticateSessionsHandler.GetPosition(initialcirpack.CircuitCode.Code); 157 startpos = m_authenticateSessionsHandler.GetPosition(initialcirpack.CircuitCode.Code);
116 158
159
160 // While working on this, the BlockingQueue had me fooled for a bit.
161 // The Blocking queue causes the thread to stop until there's something
162 // in it to process. it's an on-purpose threadlock though because
163 // without it, the clientloop will suck up all sim resources.
164
117 PacketQueue = new BlockingQueue<QueItem>(); 165 PacketQueue = new BlockingQueue<QueItem>();
118 166
167 IncomingPacketQueue = new Queue<QueItem>();
168 OutgoingPacketQueue = new Queue<QueItem>();
169 ResendOutgoingPacketQueue = new Queue<QueItem>();
170 LandOutgoingPacketQueue = new Queue<QueItem>();
171 WindOutgoingPacketQueue = new Queue<QueItem>();
172 CloudOutgoingPacketQueue = new Queue<QueItem>();
173 TaskOutgoingPacketQueue = new Queue<QueItem>();
174 TextureOutgoingPacketQueue = new Queue<QueItem>();
175 AssetOutgoingPacketQueue = new Queue<QueItem>();
176
177
119 //this.UploadAssets = new AgentAssetUpload(this, m_assetCache, m_inventoryCache); 178 //this.UploadAssets = new AgentAssetUpload(this, m_assetCache, m_inventoryCache);
120 AckTimer = new Timer(750); 179 AckTimer = new Timer(750);
121 AckTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed); 180 AckTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed);
122 AckTimer.Start(); 181 AckTimer.Start();
123 182
124 throttleTimer = new Timer(1000); 183 throttleTimer = new Timer((int)(throttletimems/throttleTimeDivisor));
125 throttleTimer.Elapsed += new ElapsedEventHandler(throttleTimer_Elapsed); 184 throttleTimer.Elapsed += new ElapsedEventHandler(throttleTimer_Elapsed);
126 throttleTimer.Start(); 185 throttleTimer.Start();
127 186
@@ -133,8 +192,97 @@ namespace OpenSim.Region.ClientStack
133 } 192 }
134 193
135 void throttleTimer_Elapsed(object sender, ElapsedEventArgs e) 194 void throttleTimer_Elapsed(object sender, ElapsedEventArgs e)
136 { 195 {
137 throttleSentPeriod = 0; 196 throttleSentPeriod = 0;
197 ResendthrottleSentPeriod = 0;
198 LandthrottleSentPeriod = 0;
199 WindthrottleSentPeriod = 0;
200 CloudthrottleSentPeriod = 0;
201 TaskthrottleSentPeriod = 0;
202 AssetthrottleSentPeriod = 0;
203 TexturethrottleSentPeriod = 0;
204
205 // I was considering this.. Will an event fire if the thread it's on is blocked?
206
207 // Then I figured out.. it doesn't really matter.. because this thread won't be blocked for long
208 // The General overhead of the UDP protocol gets sent to the queue un-throttled by this
209 // so This'll pick up about around the right time.
210
211 int MaxThrottleLoops = 5550; // 50*7 packets can be dequeued at once.
212 int throttleLoops = 0;
213
214 // We're going to dequeue all of the saved up packets until
215 // we've hit the throttle limit or there's no more packets to send
216 while ((throttleSentPeriod <= ((int)(throttleOutbound/throttleTimeDivisor)) &&
217 (ResendOutgoingPacketQueue.Count > 0 ||
218 LandOutgoingPacketQueue.Count > 0 ||
219 WindOutgoingPacketQueue.Count > 0 ||
220 CloudOutgoingPacketQueue.Count > 0 ||
221 TaskOutgoingPacketQueue.Count > 0 ||
222 AssetOutgoingPacketQueue.Count > 0 ||
223 TextureOutgoingPacketQueue.Count > 0)) && throttleLoops <= MaxThrottleLoops)
224 {
225 throttleLoops++;
226 //Now comes the fun part.. we dump all our elements into PacketQueue that we've saved up.
227 if (ResendthrottleSentPeriod <= ((int)(ResendthrottleOutbound/throttleTimeDivisor)) && ResendOutgoingPacketQueue.Count > 0)
228 {
229 QueItem qpack = ResendOutgoingPacketQueue.Dequeue();
230
231 PacketQueue.Enqueue(qpack);
232 throttleSentPeriod += qpack.Packet.ToBytes().Length;
233 ResendthrottleSentPeriod += qpack.Packet.ToBytes().Length;
234 }
235 if (LandthrottleSentPeriod <= ((int)(LandthrottleOutbound/throttleTimeDivisor)) && LandOutgoingPacketQueue.Count > 0)
236 {
237 QueItem qpack = LandOutgoingPacketQueue.Dequeue();
238
239 PacketQueue.Enqueue(qpack);
240 throttleSentPeriod += qpack.Packet.ToBytes().Length;
241 LandthrottleSentPeriod += qpack.Packet.ToBytes().Length;
242 }
243 if (WindthrottleSentPeriod <= ((int)(WindthrottleOutbound/throttleTimeDivisor)) && WindOutgoingPacketQueue.Count > 0)
244 {
245 QueItem qpack = WindOutgoingPacketQueue.Dequeue();
246
247 PacketQueue.Enqueue(qpack);
248 throttleSentPeriod += qpack.Packet.ToBytes().Length;
249 WindthrottleSentPeriod += qpack.Packet.ToBytes().Length;
250 }
251 if (CloudthrottleSentPeriod <= ((int)(CloudthrottleOutbound/throttleTimeDivisor)) && CloudOutgoingPacketQueue.Count > 0)
252 {
253 QueItem qpack = CloudOutgoingPacketQueue.Dequeue();
254
255 PacketQueue.Enqueue(qpack);
256 throttleSentPeriod += qpack.Packet.ToBytes().Length;
257 CloudthrottleSentPeriod += qpack.Packet.ToBytes().Length;
258 }
259 if (TaskthrottleSentPeriod <= ((int)(TaskthrottleOutbound/throttleTimeDivisor)) && TaskOutgoingPacketQueue.Count > 0)
260 {
261 QueItem qpack = TaskOutgoingPacketQueue.Dequeue();
262
263 PacketQueue.Enqueue(qpack);
264 throttleSentPeriod += qpack.Packet.ToBytes().Length;
265 TaskthrottleSentPeriod += qpack.Packet.ToBytes().Length;
266 }
267 if (TexturethrottleSentPeriod <= ((int)(TexturethrottleOutbound/throttleTimeDivisor)) && TextureOutgoingPacketQueue.Count > 0)
268 {
269 QueItem qpack = TextureOutgoingPacketQueue.Dequeue();
270
271 PacketQueue.Enqueue(qpack);
272 throttleSentPeriod += qpack.Packet.ToBytes().Length;
273 TexturethrottleSentPeriod += qpack.Packet.ToBytes().Length;
274 }
275 if (AssetthrottleSentPeriod <= ((int)(AssetthrottleOutbound/throttleTimeDivisor)) && AssetOutgoingPacketQueue.Count > 0)
276 {
277 QueItem qpack = AssetOutgoingPacketQueue.Dequeue();
278
279 PacketQueue.Enqueue(qpack);
280 throttleSentPeriod += qpack.Packet.ToBytes().Length;
281 AssetthrottleSentPeriod += qpack.Packet.ToBytes().Length;
282 }
283
284 }
285
138 } 286 }
139 287
140 public LLUUID SessionId 288 public LLUUID SessionId
@@ -277,7 +425,7 @@ namespace OpenSim.Region.ClientStack
277 else 425 else
278 { 426 {
279 // Throw it back on the queue if it's going to cause us to flood the client 427 // Throw it back on the queue if it's going to cause us to flood the client
280 if (throttleSentPeriod > throttleOutbound) 428 if (throttleSentPeriod > throttleOutboundMax)
281 { 429 {
282 PacketQueue.Enqueue(nextPacket); 430 PacketQueue.Enqueue(nextPacket);
283 MainLog.Instance.Verbose("Client over throttle limit, requeuing packet"); 431 MainLog.Instance.Verbose("Client over throttle limit, requeuing packet");