aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules
diff options
context:
space:
mode:
authorUbitUmarov2016-07-10 15:25:05 +0100
committerUbitUmarov2016-07-10 15:25:05 +0100
commite6d57a1e49ce6f284dc03f7b8a57d08ade7b7ce4 (patch)
tree07a802d64816f25e2d42ca49cf22b187479fff46 /OpenSim/Region/CoreModules
parentMerge branch 'master' of opensimulator.org:/var/git/opensim (diff)
downloadopensim-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')
-rw-r--r--OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs290
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