diff options
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs | 119 |
1 files changed, 106 insertions, 13 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs index 4bfdbff..8cba6c8 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs | |||
@@ -61,7 +61,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
61 | public Hashtable request; | 61 | public Hashtable request; |
62 | } | 62 | } |
63 | 63 | ||
64 | public struct aPollResponse | 64 | public class aPollResponse |
65 | { | 65 | { |
66 | public Hashtable response; | 66 | public Hashtable response; |
67 | public int bytes; | 67 | public int bytes; |
@@ -151,13 +151,18 @@ namespace OpenSim.Region.ClientStack.Linden | |||
151 | } | 151 | } |
152 | 152 | ||
153 | // 0.125f converts from bits to bytes | 153 | // 0.125f converts from bits to bytes |
154 | //int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; | 154 | //int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); |
155 | // int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; | 155 | //pos += 4; |
156 | // int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; | 156 | // int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); |
157 | // int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; | 157 | //pos += 4; |
158 | // int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; | 158 | // int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); |
159 | // pos += 4; | ||
160 | // int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); | ||
161 | // pos += 4; | ||
162 | // int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); | ||
163 | // pos += 4; | ||
159 | pos = pos + 20; | 164 | pos = pos + 20; |
160 | int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; | 165 | int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); //pos += 4; |
161 | //int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); | 166 | //int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); |
162 | return texture; | 167 | return texture; |
163 | } | 168 | } |
@@ -205,7 +210,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
205 | new Dictionary<UUID, aPollResponse>(); | 210 | new Dictionary<UUID, aPollResponse>(); |
206 | 211 | ||
207 | private Scene m_scene; | 212 | private Scene m_scene; |
208 | 213 | private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000); | |
209 | public PollServiceTextureEventArgs(UUID pId, Scene scene) : | 214 | public PollServiceTextureEventArgs(UUID pId, Scene scene) : |
210 | base(null, null, null, null, pId, int.MaxValue) | 215 | base(null, null, null, null, pId, int.MaxValue) |
211 | { | 216 | { |
@@ -214,7 +219,12 @@ namespace OpenSim.Region.ClientStack.Linden | |||
214 | HasEvents = (x, y) => | 219 | HasEvents = (x, y) => |
215 | { | 220 | { |
216 | lock (responses) | 221 | lock (responses) |
217 | return responses.ContainsKey(x); | 222 | { |
223 | bool ret = m_throttler.hasEvents(x, responses); | ||
224 | m_throttler.ProcessTime(); | ||
225 | return ret; | ||
226 | |||
227 | } | ||
218 | }; | 228 | }; |
219 | GetEvents = (x, y) => | 229 | GetEvents = (x, y) => |
220 | { | 230 | { |
@@ -281,19 +291,27 @@ namespace OpenSim.Region.ClientStack.Linden | |||
281 | response["reusecontext"] = false; | 291 | response["reusecontext"] = false; |
282 | 292 | ||
283 | lock (responses) | 293 | lock (responses) |
284 | responses[requestID] = new aPollResponse() {bytes = 0,response = response}; | 294 | responses[requestID] = new aPollResponse() {bytes = 0, response = response}; |
285 | 295 | ||
286 | return; | 296 | return; |
287 | } | 297 | } |
288 | 298 | ||
289 | response = m_getTextureHandler.Handle(requestinfo.request); | 299 | response = m_getTextureHandler.Handle(requestinfo.request); |
290 | lock (responses) | 300 | lock (responses) |
291 | responses[requestID] = new aPollResponse() { bytes = (int)response["int_bytes"], response = response}; | 301 | { |
302 | responses[requestID] = new aPollResponse() | ||
303 | { | ||
304 | bytes = (int) response["int_bytes"], | ||
305 | response = response | ||
306 | }; | ||
307 | |||
308 | } | ||
309 | m_throttler.ProcessTime(); | ||
292 | } | 310 | } |
293 | 311 | ||
294 | internal void UpdateThrottle(int pimagethrottle) | 312 | internal void UpdateThrottle(int pimagethrottle) |
295 | { | 313 | { |
296 | 314 | m_throttler.ThrottleBytes = pimagethrottle; | |
297 | } | 315 | } |
298 | } | 316 | } |
299 | 317 | ||
@@ -347,4 +365,79 @@ namespace OpenSim.Region.ClientStack.Linden | |||
347 | } | 365 | } |
348 | } | 366 | } |
349 | } | 367 | } |
368 | |||
369 | internal sealed class CapsDataThrottler | ||
370 | { | ||
371 | |||
372 | private volatile int currenttime = 0; | ||
373 | private volatile int lastTimeElapsed = 0; | ||
374 | private volatile int BytesSent = 0; | ||
375 | private int oversizedImages = 0; | ||
376 | public CapsDataThrottler(int pBytes, int max, int min) | ||
377 | { | ||
378 | ThrottleBytes = pBytes; | ||
379 | lastTimeElapsed = Util.EnvironmentTickCount(); | ||
380 | } | ||
381 | public bool hasEvents(UUID key, Dictionary<UUID, GetTextureModule.aPollResponse> responses) | ||
382 | { | ||
383 | PassTime(); | ||
384 | // Note, this is called IN LOCK | ||
385 | bool haskey = responses.ContainsKey(key); | ||
386 | if (!haskey) | ||
387 | { | ||
388 | return false; | ||
389 | } | ||
390 | GetTextureModule.aPollResponse response; | ||
391 | if (responses.TryGetValue(key,out response)) | ||
392 | { | ||
393 | |||
394 | // Normal | ||
395 | if (BytesSent + response.bytes <= ThrottleBytes) | ||
396 | { | ||
397 | BytesSent += response.bytes; | ||
398 | //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + 1000, unlockyn = false }; | ||
399 | //m_actions.Add(timeBasedAction); | ||
400 | return true; | ||
401 | } | ||
402 | // Big textures | ||
403 | else if (response.bytes > ThrottleBytes && oversizedImages <= ((ThrottleBytes%50000) + 1)) | ||
404 | { | ||
405 | Interlocked.Increment(ref oversizedImages); | ||
406 | BytesSent += response.bytes; | ||
407 | //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + (((response.bytes % ThrottleBytes)+1)*1000) , unlockyn = false }; | ||
408 | //m_actions.Add(timeBasedAction); | ||
409 | return true; | ||
410 | } | ||
411 | else | ||
412 | { | ||
413 | return false; | ||
414 | } | ||
415 | } | ||
416 | |||
417 | return haskey; | ||
418 | } | ||
419 | public void ProcessTime() | ||
420 | { | ||
421 | PassTime(); | ||
422 | } | ||
423 | |||
424 | |||
425 | private void PassTime() | ||
426 | { | ||
427 | currenttime = Util.EnvironmentTickCount(); | ||
428 | int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed); | ||
429 | //processTimeBasedActions(responses); | ||
430 | if (Util.EnvironmentTickCountSubtract(currenttime, timeElapsed) >= 1000) | ||
431 | { | ||
432 | lastTimeElapsed = Util.EnvironmentTickCount(); | ||
433 | BytesSent -= ThrottleBytes; | ||
434 | if (BytesSent < 0) BytesSent = 0; | ||
435 | if (BytesSent < ThrottleBytes) | ||
436 | { | ||
437 | oversizedImages = 0; | ||
438 | } | ||
439 | } | ||
440 | } | ||
441 | public int ThrottleBytes; | ||
442 | } | ||
350 | } | 443 | } |