diff options
author | UbitUmarov | 2016-07-10 15:25:05 +0100 |
---|---|---|
committer | UbitUmarov | 2016-07-10 15:25:05 +0100 |
commit | e6d57a1e49ce6f284dc03f7b8a57d08ade7b7ce4 (patch) | |
tree | 07a802d64816f25e2d42ca49cf22b187479fff46 /OpenSim/Region/CoreModules/Agent/Xfer | |
parent | Merge branch 'master' of opensimulator.org:/var/git/opensim (diff) | |
download | opensim-SC-e6d57a1e49ce6f284dc03f7b8a57d08ade7b7ce4.zip opensim-SC-e6d57a1e49ce6f284dc03f7b8a57d08ade7b7ce4.tar.gz opensim-SC-e6d57a1e49ce6f284dc03f7b8a57d08ade7b7ce4.tar.bz2 opensim-SC-e6d57a1e49ce6f284dc03f7b8a57d08ade7b7ce4.tar.xz |
change Xfermanager file sending
Diffstat (limited to 'OpenSim/Region/CoreModules/Agent/Xfer')
-rw-r--r-- | OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs | 290 |
1 files changed, 192 insertions, 98 deletions
diff --git a/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs b/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs index 468dccf..437cbcd 100644 --- a/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs +++ b/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs | |||
@@ -49,12 +49,11 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
49 | private Dictionary<ulong, XferDownLoad> Transfers = new Dictionary<ulong, XferDownLoad>(); | 49 | private Dictionary<ulong, XferDownLoad> Transfers = new Dictionary<ulong, XferDownLoad>(); |
50 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 50 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
51 | 51 | ||
52 | 52 | private object timeTickLock = new object(); | |
53 | private object timeTickLock = new object(); | 53 | private double lastTimeTick = 0.0; |
54 | private double lastTimeTick = 0.0; | 54 | private double lastFilesExpire = 0.0; |
55 | private bool inTimeTick = false; | 55 | private bool inTimeTick = false; |
56 | private double lastFilesExpire = 0.0; | 56 | |
57 | |||
58 | public struct XferRequest | 57 | public struct XferRequest |
59 | { | 58 | { |
60 | public IClientAPI remoteClient; | 59 | public IClientAPI remoteClient; |
@@ -81,15 +80,15 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
81 | public void AddRegion(Scene scene) | 80 | public void AddRegion(Scene scene) |
82 | { | 81 | { |
83 | m_scene = scene; | 82 | m_scene = scene; |
83 | m_scene.RegisterModuleInterface<IXfer>(this); | ||
84 | m_scene.EventManager.OnNewClient += NewClient; | 84 | m_scene.EventManager.OnNewClient += NewClient; |
85 | m_scene.EventManager.OnRegionHeartbeatEnd += OnTimeTick; | 85 | m_scene.EventManager.OnRegionHeartbeatEnd += OnTimeTick; |
86 | m_scene.RegisterModuleInterface<IXfer>(this); | ||
87 | } | 86 | } |
88 | 87 | ||
89 | public void RemoveRegion(Scene scene) | 88 | public void RemoveRegion(Scene scene) |
90 | { | 89 | { |
91 | m_scene.EventManager.OnNewClient -= NewClient; | 90 | m_scene.EventManager.OnNewClient -= NewClient; |
92 | m_scene.EventManager.OnRegionHeartbeatEnd -= OnTimeTick; | 91 | m_scene.EventManager.OnRegionHeartbeatEnd -= OnTimeTick; |
93 | 92 | ||
94 | m_scene.UnregisterModuleInterface<IXfer>(this); | 93 | m_scene.UnregisterModuleInterface<IXfer>(this); |
95 | m_scene = null; | 94 | m_scene = null; |
@@ -123,7 +122,7 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
123 | if(!inTimeTick) | 122 | if(!inTimeTick) |
124 | { | 123 | { |
125 | double now = Util.GetTimeStampMS(); | 124 | double now = Util.GetTimeStampMS(); |
126 | if(now - lastTimeTick > 1500.0) // 1.5 second | 125 | if(now - lastTimeTick > 1750.0) |
127 | { | 126 | { |
128 | inTimeTick = true; | 127 | inTimeTick = true; |
129 | 128 | ||
@@ -197,7 +196,7 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
197 | } | 196 | } |
198 | } | 197 | } |
199 | } | 198 | } |
200 | 199 | ||
201 | public void NewClient(IClientAPI client) | 200 | public void NewClient(IClientAPI client) |
202 | { | 201 | { |
203 | client.OnRequestXfer += RequestXfer; | 202 | client.OnRequestXfer += RequestXfer; |
@@ -205,9 +204,49 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
205 | client.OnAbortXfer += AbortXfer; | 204 | client.OnAbortXfer += AbortXfer; |
206 | } | 205 | } |
207 | 206 | ||
207 | public void OnClientClosed(IClientAPI client) | ||
208 | { | ||
209 | client.OnRequestXfer -= RequestXfer; | ||
210 | client.OnConfirmXfer -= AckPacket; | ||
211 | client.OnAbortXfer -= AbortXfer; | ||
212 | } | ||
213 | |||
214 | private void RemoveOrDecrementFile(string fileName) | ||
215 | { | ||
216 | // NewFiles must be locked | ||
217 | |||
218 | if (NewFiles.ContainsKey(fileName)) | ||
219 | { | ||
220 | if (NewFiles[fileName].refsCount == 1) | ||
221 | NewFiles.Remove(fileName); | ||
222 | else | ||
223 | NewFiles[fileName].refsCount--; | ||
224 | } | ||
225 | } | ||
226 | |||
208 | public void transfersTimeTick(double now) | 227 | public void transfersTimeTick(double now) |
209 | { | 228 | { |
210 | 229 | XferDownLoad[] xfrs; | |
230 | lock(Transfers) | ||
231 | { | ||
232 | if(Transfers.Count == 0) | ||
233 | return; | ||
234 | |||
235 | xfrs = new XferDownLoad[Transfers.Count]; | ||
236 | Transfers.Values.CopyTo(xfrs,0); | ||
237 | } | ||
238 | foreach(XferDownLoad xfr in xfrs) | ||
239 | { | ||
240 | if(xfr.checkTime(now)) | ||
241 | { | ||
242 | ulong xfrID = xfr.XferID; | ||
243 | lock(Transfers) | ||
244 | { | ||
245 | if(Transfers.ContainsKey(xfrID)) | ||
246 | Transfers.Remove(xfrID); | ||
247 | } | ||
248 | } | ||
249 | } | ||
211 | } | 250 | } |
212 | 251 | ||
213 | /// <summary> | 252 | /// <summary> |
@@ -222,80 +261,49 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
222 | { | 261 | { |
223 | if (NewFiles.ContainsKey(fileName)) | 262 | if (NewFiles.ContainsKey(fileName)) |
224 | { | 263 | { |
225 | if (!Transfers.ContainsKey(xferID)) | 264 | lock(Transfers) |
226 | { | 265 | { |
227 | byte[] fileData = NewFiles[fileName].Data; | 266 | if (!Transfers.ContainsKey(xferID)) |
228 | XferDownLoad transaction = new XferDownLoad(fileName, fileData, xferID, remoteClient); | 267 | { |
229 | if (fileName.StartsWith("inventory_")) | 268 | byte[] fileData = NewFiles[fileName].Data; |
230 | transaction.isTaskInventory = true; | 269 | XferDownLoad transaction = |
231 | 270 | new XferDownLoad(fileName, fileData, xferID, remoteClient); | |
232 | Transfers.Add(xferID, transaction); | ||
233 | 271 | ||
234 | if (transaction.StartSend()) | 272 | Transfers.Add(xferID, transaction); |
235 | RemoveXferData(xferID); | ||
236 | 273 | ||
237 | // The transaction for this file is either complete or on its way | 274 | transaction.StartSend(); |
238 | RemoveOrDecrement(fileName); | ||
239 | 275 | ||
276 | // The transaction for this file is on its way | ||
277 | RemoveOrDecrementFile(fileName); | ||
278 | } | ||
240 | } | 279 | } |
241 | } | 280 | } |
242 | else | 281 | else |
243 | m_log.WarnFormat("[Xfer]: {0} not found", fileName); | 282 | m_log.WarnFormat("[Xfer]: {0} not found", fileName); |
244 | |||
245 | } | 283 | } |
246 | } | 284 | } |
247 | 285 | ||
248 | public void AckPacket(IClientAPI remoteClient, ulong xferID, uint packet) | 286 | public void AckPacket(IClientAPI remoteClient, ulong xferID, uint packet) |
249 | { | 287 | { |
250 | lock (NewFiles) // This is actually to lock Transfers | 288 | lock (Transfers) |
251 | { | 289 | { |
252 | if (Transfers.ContainsKey(xferID)) | 290 | if (Transfers.ContainsKey(xferID)) |
253 | { | 291 | { |
254 | XferDownLoad dl = Transfers[xferID]; | ||
255 | if (Transfers[xferID].AckPacket(packet)) | 292 | if (Transfers[xferID].AckPacket(packet)) |
256 | { | 293 | Transfers.Remove(xferID); |
257 | RemoveXferData(xferID); | ||
258 | RemoveOrDecrement(dl.FileName); | ||
259 | } | ||
260 | } | 294 | } |
261 | } | 295 | } |
262 | } | 296 | } |
263 | 297 | ||
264 | private void RemoveXferData(ulong xferID) | ||
265 | { | ||
266 | // NewFiles must be locked! | ||
267 | if (Transfers.ContainsKey(xferID)) | ||
268 | { | ||
269 | XferModule.XferDownLoad xferItem = Transfers[xferID]; | ||
270 | //string filename = xferItem.FileName; | ||
271 | Transfers.Remove(xferID); | ||
272 | xferItem.Data = new byte[0]; // Clear the data | ||
273 | xferItem.DataPointer = 0; | ||
274 | |||
275 | } | ||
276 | } | ||
277 | |||
278 | public void AbortXfer(IClientAPI remoteClient, ulong xferID) | 298 | public void AbortXfer(IClientAPI remoteClient, ulong xferID) |
279 | { | 299 | { |
280 | lock (NewFiles) | 300 | lock (Transfers) |
281 | { | 301 | { |
282 | if (Transfers.ContainsKey(xferID)) | 302 | if (Transfers.ContainsKey(xferID)) |
283 | RemoveOrDecrement(Transfers[xferID].FileName); | 303 | { |
284 | 304 | Transfers[xferID].done(); | |
285 | RemoveXferData(xferID); | 305 | Transfers.Remove(xferID); |
286 | } | 306 | } |
287 | } | ||
288 | |||
289 | private void RemoveOrDecrement(string fileName) | ||
290 | { | ||
291 | // NewFiles must be locked | ||
292 | |||
293 | if (NewFiles.ContainsKey(fileName)) | ||
294 | { | ||
295 | if (NewFiles[fileName].refsCount == 1) | ||
296 | NewFiles.Remove(fileName); | ||
297 | else | ||
298 | NewFiles[fileName].refsCount--; | ||
299 | } | 307 | } |
300 | } | 308 | } |
301 | 309 | ||
@@ -304,14 +312,19 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
304 | public class XferDownLoad | 312 | public class XferDownLoad |
305 | { | 313 | { |
306 | public IClientAPI Client; | 314 | public IClientAPI Client; |
307 | private bool complete; | ||
308 | public byte[] Data = new byte[0]; | 315 | public byte[] Data = new byte[0]; |
309 | public int DataPointer = 0; | ||
310 | public string FileName = String.Empty; | 316 | public string FileName = String.Empty; |
311 | public uint Packet = 0; | ||
312 | public uint Serial = 1; | ||
313 | public ulong XferID = 0; | 317 | public ulong XferID = 0; |
314 | public bool isTaskInventory = false; | 318 | public bool isDeleted = false; |
319 | |||
320 | private object myLock = new object(); | ||
321 | private double lastsendTimeMS; | ||
322 | private int LastPacket; | ||
323 | private int lastBytes; | ||
324 | private int lastSentPacket; | ||
325 | private int lastAckPacket; | ||
326 | private int burstSize; | ||
327 | private int retries = 0; | ||
315 | 328 | ||
316 | public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client) | 329 | public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client) |
317 | { | 330 | { |
@@ -325,32 +338,97 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
325 | { | 338 | { |
326 | } | 339 | } |
327 | 340 | ||
341 | public void done() | ||
342 | { | ||
343 | if(!isDeleted) | ||
344 | { | ||
345 | Data = new byte[0]; | ||
346 | isDeleted = true; | ||
347 | } | ||
348 | } | ||
349 | |||
328 | /// <summary> | 350 | /// <summary> |
329 | /// Start a transfer | 351 | /// Start a transfer |
330 | /// </summary> | 352 | /// </summary> |
331 | /// <returns>True if the transfer is complete, false if not</returns> | 353 | /// <returns>True if the transfer is complete, false if not</returns> |
332 | public bool StartSend() | 354 | public void StartSend() |
333 | { | 355 | { |
334 | if (Data.Length < 1000) | 356 | lock(myLock) |
335 | { | 357 | { |
336 | // for now (testing) we only support files under 1000 bytes | 358 | if(Data.Length == 0) //?? |
337 | byte[] transferData = new byte[Data.Length + 4]; | 359 | { |
338 | Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4); | 360 | LastPacket = 0; |
339 | Array.Copy(Data, 0, transferData, 4, Data.Length); | 361 | lastBytes = 0; |
340 | Client.SendXferPacket(XferID, 0 + 0x80000000, transferData, isTaskInventory); | 362 | burstSize = 0; |
341 | complete = true; | 363 | } |
364 | else | ||
365 | { | ||
366 | // payload of 1024bytes | ||
367 | LastPacket = Data.Length >> 10; | ||
368 | lastBytes = Data.Length & 0x3ff; | ||
369 | if(lastBytes == 0) | ||
370 | { | ||
371 | lastBytes = 1024; | ||
372 | LastPacket--; | ||
373 | } | ||
374 | burstSize = Client.GetAgentThrottleSilent((int)ThrottleOutPacketType.Asset) >> 11; | ||
375 | } | ||
376 | |||
377 | lastAckPacket = -1; | ||
378 | lastSentPacket = -1; | ||
379 | |||
380 | double now = Util.GetTimeStampMS(); | ||
381 | |||
382 | SendBurst(now); | ||
383 | return; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | private void SendBurst(double now) | ||
388 | { | ||
389 | int start = lastAckPacket + 1; | ||
390 | int end = start + burstSize; | ||
391 | if (end > LastPacket) | ||
392 | end = LastPacket; | ||
393 | while(start <= end) | ||
394 | SendPacket(start++ , now); | ||
395 | } | ||
396 | |||
397 | private void SendPacket(int pkt, double now) | ||
398 | { | ||
399 | if(pkt > LastPacket) | ||
400 | return; | ||
401 | |||
402 | int pktsize; | ||
403 | uint pktid; | ||
404 | if (pkt == LastPacket) | ||
405 | { | ||
406 | pktsize = lastBytes; | ||
407 | pktid = (uint)pkt | 0x80000000u; | ||
342 | } | 408 | } |
343 | else | 409 | else |
344 | { | 410 | { |
345 | byte[] transferData = new byte[1000 + 4]; | 411 | pktsize = 1024; |
412 | pktid = (uint)pkt; | ||
413 | } | ||
414 | |||
415 | byte[] transferData; | ||
416 | if(pkt == 0) | ||
417 | { | ||
418 | transferData = new byte[pktsize + 4]; | ||
346 | Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4); | 419 | Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4); |
347 | Array.Copy(Data, 0, transferData, 4, 1000); | 420 | Array.Copy(Data, 0, transferData, 4, pktsize); |
348 | Client.SendXferPacket(XferID, 0, transferData, isTaskInventory); | 421 | } |
349 | Packet++; | 422 | else |
350 | DataPointer = 1000; | 423 | { |
424 | transferData = new byte[pktsize]; | ||
425 | Array.Copy(Data, pkt << 10, transferData, 0, pktsize); | ||
351 | } | 426 | } |
352 | 427 | ||
353 | return complete; | 428 | Client.SendXferPacket(XferID, pktid, transferData, false); |
429 | |||
430 | lastSentPacket = pkt; | ||
431 | lastsendTimeMS = now; | ||
354 | } | 432 | } |
355 | 433 | ||
356 | /// <summary> | 434 | /// <summary> |
@@ -360,30 +438,46 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
360 | /// <returns>True if the transfer is complete, false otherwise</returns> | 438 | /// <returns>True if the transfer is complete, false otherwise</returns> |
361 | public bool AckPacket(uint packet) | 439 | public bool AckPacket(uint packet) |
362 | { | 440 | { |
363 | if (!complete) | 441 | lock(myLock) |
364 | { | 442 | { |
365 | if ((Data.Length - DataPointer) > 1000) | 443 | if(isDeleted) |
444 | return true; | ||
445 | |||
446 | packet &= 0x7fffffff; | ||
447 | if(lastAckPacket < packet) | ||
448 | lastAckPacket = (int)packet; | ||
449 | |||
450 | if(lastAckPacket == LastPacket) | ||
366 | { | 451 | { |
367 | byte[] transferData = new byte[1000]; | 452 | done(); |
368 | Array.Copy(Data, DataPointer, transferData, 0, 1000); | 453 | return true; |
369 | Client.SendXferPacket(XferID, Packet, transferData, isTaskInventory); | ||
370 | Packet++; | ||
371 | DataPointer += 1000; | ||
372 | } | 454 | } |
373 | else | 455 | double now = Util.GetTimeStampMS(); |
456 | SendPacket(lastSentPacket + 1, now); | ||
457 | return false; | ||
458 | } | ||
459 | } | ||
460 | |||
461 | public bool checkTime(double now) | ||
462 | { | ||
463 | if(Monitor.TryEnter(myLock)) | ||
464 | { | ||
465 | if(!isDeleted) | ||
374 | { | 466 | { |
375 | byte[] transferData = new byte[Data.Length - DataPointer]; | 467 | double timeMS = now - lastsendTimeMS; |
376 | Array.Copy(Data, DataPointer, transferData, 0, Data.Length - DataPointer); | 468 | if(timeMS > 60000.0) |
377 | uint endPacket = Packet |= (uint) 0x80000000; | 469 | done(); |
378 | Client.SendXferPacket(XferID, endPacket, transferData, isTaskInventory); | 470 | else if(timeMS > 3500.0 && retries++ < 3) |
379 | Packet++; | 471 | { |
380 | DataPointer += (Data.Length - DataPointer); | 472 | burstSize >>= 1; |
381 | 473 | SendBurst(now); | |
382 | complete = true; | 474 | } |
383 | } | 475 | } |
384 | } | ||
385 | 476 | ||
386 | return complete; | 477 | Monitor.Exit(myLock); |
478 | return isDeleted; | ||
479 | } | ||
480 | return false; | ||
387 | } | 481 | } |
388 | } | 482 | } |
389 | 483 | ||