aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs
diff options
context:
space:
mode:
authoronefang2019-05-19 21:24:15 +1000
committeronefang2019-05-19 21:24:15 +1000
commit5e4d6cab00cb29cd088ab7b62ab13aff103b64cb (patch)
treea9fbc62df9eb2d1d9ba2698d8552eae71eca20d8 /OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs
parentAdd a build script. (diff)
downloadopensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.zip
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.gz
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.bz2
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.xz
Dump OpenSim 0.9.0.1 into it's own branch.
Diffstat (limited to 'OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs')
-rw-r--r--OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs365
1 files changed, 269 insertions, 96 deletions
diff --git a/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs b/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs
index 4299726..1b6401a 100644
--- a/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs
@@ -28,10 +28,12 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.Threading;
31using Nini.Config; 32using Nini.Config;
32using log4net; 33using log4net;
33using OpenMetaverse; 34using OpenMetaverse;
34using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Framework.Monitoring;
35using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
37 39
@@ -45,9 +47,13 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
45 private Scene m_scene; 47 private Scene m_scene;
46 private Dictionary<string, FileData> NewFiles = new Dictionary<string, FileData>(); 48 private Dictionary<string, FileData> NewFiles = new Dictionary<string, FileData>();
47 private Dictionary<ulong, XferDownLoad> Transfers = new Dictionary<ulong, XferDownLoad>(); 49 private Dictionary<ulong, XferDownLoad> Transfers = new Dictionary<ulong, XferDownLoad>();
48
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 51
52 private object timeTickLock = new object();
53 private double lastTimeTick = 0.0;
54 private double lastFilesExpire = 0.0;
55 private bool inTimeTick = false;
56
51 public struct XferRequest 57 public struct XferRequest
52 { 58 {
53 public IClientAPI remoteClient; 59 public IClientAPI remoteClient;
@@ -59,26 +65,30 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
59 private class FileData 65 private class FileData
60 { 66 {
61 public byte[] Data; 67 public byte[] Data;
62 public int Count; 68 public int refsCount;
69 public double timeStampMS;
63 } 70 }
64 71
65 #region INonSharedRegionModule Members 72 #region INonSharedRegionModule Members
66 73
67 public void Initialise(IConfigSource config) 74 public void Initialise(IConfigSource config)
68 { 75 {
76 lastTimeTick = Util.GetTimeStampMS() + 30000.0;
77 lastFilesExpire = lastTimeTick + 180000.0;
69 } 78 }
70 79
71 public void AddRegion(Scene scene) 80 public void AddRegion(Scene scene)
72 { 81 {
73 m_scene = scene; 82 m_scene = scene;
74 m_scene.EventManager.OnNewClient += NewClient;
75
76 m_scene.RegisterModuleInterface<IXfer>(this); 83 m_scene.RegisterModuleInterface<IXfer>(this);
84 m_scene.EventManager.OnNewClient += NewClient;
85 m_scene.EventManager.OnRegionHeartbeatEnd += OnTimeTick;
77 } 86 }
78 87
79 public void RemoveRegion(Scene scene) 88 public void RemoveRegion(Scene scene)
80 { 89 {
81 m_scene.EventManager.OnNewClient -= NewClient; 90 m_scene.EventManager.OnNewClient -= NewClient;
91 m_scene.EventManager.OnRegionHeartbeatEnd -= OnTimeTick;
82 92
83 m_scene.UnregisterModuleInterface<IXfer>(this); 93 m_scene.UnregisterModuleInterface<IXfer>(this);
84 m_scene = null; 94 m_scene = null;
@@ -104,6 +114,41 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
104 114
105 #endregion 115 #endregion
106 116
117 public void OnTimeTick(Scene scene)
118 {
119 // we are on a heartbeat thread we there can be several
120 if(Monitor.TryEnter(timeTickLock))
121 {
122 if(!inTimeTick)
123 {
124 double now = Util.GetTimeStampMS();
125 if(now - lastTimeTick > 1750.0)
126 {
127
128 if(Transfers.Count == 0 && NewFiles.Count == 0)
129 lastTimeTick = now;
130 else
131 {
132 inTimeTick = true;
133
134 //don't overload busy heartbeat
135 WorkManager.RunInThreadPool(
136 delegate
137 {
138 transfersTimeTick(now);
139 expireFiles(now);
140
141 lastTimeTick = now;
142 inTimeTick = false;
143 },
144 null,
145 "XferTimeTick");
146 }
147 }
148 }
149 Monitor.Exit(timeTickLock);
150 }
151 }
107 #region IXfer Members 152 #region IXfer Members
108 153
109 /// <summary> 154 /// <summary>
@@ -118,24 +163,45 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
118 { 163 {
119 lock (NewFiles) 164 lock (NewFiles)
120 { 165 {
166 double now = Util.GetTimeStampMS();
121 if (NewFiles.ContainsKey(fileName)) 167 if (NewFiles.ContainsKey(fileName))
122 { 168 {
123 NewFiles[fileName].Count++; 169 NewFiles[fileName].refsCount++;
124 NewFiles[fileName].Data = data; 170 NewFiles[fileName].Data = data;
171 NewFiles[fileName].timeStampMS = now;
125 } 172 }
126 else 173 else
127 { 174 {
128 FileData fd = new FileData(); 175 FileData fd = new FileData();
129 fd.Count = 1; 176 fd.refsCount = 1;
130 fd.Data = data; 177 fd.Data = data;
178 fd.timeStampMS = now;
131 NewFiles.Add(fileName, fd); 179 NewFiles.Add(fileName, fd);
132 } 180 }
133 } 181 }
134
135 return true; 182 return true;
136 } 183 }
137 184
138 #endregion 185 #endregion
186 public void expireFiles(double now)
187 {
188 lock (NewFiles)
189 {
190 // hopefully we will not have many files so nasty code will do it
191 if(now - lastFilesExpire > 120000.0)
192 {
193 lastFilesExpire = now;
194 List<string> expires = new List<string>();
195 foreach(string fname in NewFiles.Keys)
196 {
197 if(NewFiles[fname].refsCount == 0 && now - NewFiles[fname].timeStampMS > 120000.0)
198 expires.Add(fname);
199 }
200 foreach(string fname in expires)
201 NewFiles.Remove(fname);
202 }
203 }
204 }
139 205
140 public void NewClient(IClientAPI client) 206 public void NewClient(IClientAPI client)
141 { 207 {
@@ -144,6 +210,51 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
144 client.OnAbortXfer += AbortXfer; 210 client.OnAbortXfer += AbortXfer;
145 } 211 }
146 212
213 public void OnClientClosed(IClientAPI client)
214 {
215 client.OnRequestXfer -= RequestXfer;
216 client.OnConfirmXfer -= AckPacket;
217 client.OnAbortXfer -= AbortXfer;
218 }
219
220 private void RemoveOrDecrementFile(string fileName)
221 {
222 // NewFiles must be locked
223
224 if (NewFiles.ContainsKey(fileName))
225 {
226 if (NewFiles[fileName].refsCount == 1)
227 NewFiles.Remove(fileName);
228 else
229 NewFiles[fileName].refsCount--;
230 }
231 }
232
233 public void transfersTimeTick(double now)
234 {
235 XferDownLoad[] xfrs;
236 lock(Transfers)
237 {
238 if(Transfers.Count == 0)
239 return;
240
241 xfrs = new XferDownLoad[Transfers.Count];
242 Transfers.Values.CopyTo(xfrs,0);
243 }
244 foreach(XferDownLoad xfr in xfrs)
245 {
246 if(xfr.checkTime(now))
247 {
248 ulong xfrID = xfr.XferID;
249 lock(Transfers)
250 {
251 if(Transfers.ContainsKey(xfrID))
252 Transfers.Remove(xfrID);
253 }
254 }
255 }
256 }
257
147 /// <summary> 258 /// <summary>
148 /// 259 ///
149 /// </summary> 260 /// </summary>
@@ -156,78 +267,52 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
156 { 267 {
157 if (NewFiles.ContainsKey(fileName)) 268 if (NewFiles.ContainsKey(fileName))
158 { 269 {
159 if (!Transfers.ContainsKey(xferID)) 270 lock(Transfers)
160 { 271 {
161 byte[] fileData = NewFiles[fileName].Data; 272 if (!Transfers.ContainsKey(xferID))
162 XferDownLoad transaction = new XferDownLoad(fileName, fileData, xferID, remoteClient); 273 {
163 274 byte[] fileData = NewFiles[fileName].Data;
164 Transfers.Add(xferID, transaction); 275 int burstSize = remoteClient.GetAgentThrottleSilent((int)ThrottleOutPacketType.Asset) >> 11;
165 276 if(Transfers.Count > 1)
166 if (transaction.StartSend()) 277 burstSize /= Transfers.Count;
167 RemoveXferData(xferID); 278 XferDownLoad transaction =
168 279 new XferDownLoad(fileName, fileData, xferID, remoteClient, burstSize);
169 // The transaction for this file is either complete or on its way 280
170 RemoveOrDecrement(fileName); 281 Transfers.Add(xferID, transaction);
171 282
283 transaction.StartSend();
284
285 // The transaction for this file is on its way
286 RemoveOrDecrementFile(fileName);
287 }
172 } 288 }
173 } 289 }
174 else 290 else
175 m_log.WarnFormat("[Xfer]: {0} not found", fileName); 291 m_log.WarnFormat("[Xfer]: {0} not found", fileName);
176
177 } 292 }
178 } 293 }
179 294
180 public void AckPacket(IClientAPI remoteClient, ulong xferID, uint packet) 295 public void AckPacket(IClientAPI remoteClient, ulong xferID, uint packet)
181 { 296 {
182 lock (NewFiles) // This is actually to lock Transfers 297 lock (Transfers)
183 { 298 {
184 if (Transfers.ContainsKey(xferID)) 299 if (Transfers.ContainsKey(xferID))
185 { 300 {
186 XferDownLoad dl = Transfers[xferID];
187 if (Transfers[xferID].AckPacket(packet)) 301 if (Transfers[xferID].AckPacket(packet))
188 { 302 Transfers.Remove(xferID);
189 RemoveXferData(xferID);
190 RemoveOrDecrement(dl.FileName);
191 }
192 } 303 }
193 } 304 }
194 } 305 }
195 306
196 private void RemoveXferData(ulong xferID)
197 {
198 // NewFiles must be locked!
199 if (Transfers.ContainsKey(xferID))
200 {
201 XferModule.XferDownLoad xferItem = Transfers[xferID];
202 //string filename = xferItem.FileName;
203 Transfers.Remove(xferID);
204 xferItem.Data = new byte[0]; // Clear the data
205 xferItem.DataPointer = 0;
206
207 }
208 }
209
210 public void AbortXfer(IClientAPI remoteClient, ulong xferID) 307 public void AbortXfer(IClientAPI remoteClient, ulong xferID)
211 { 308 {
212 lock (NewFiles) 309 lock (Transfers)
213 { 310 {
214 if (Transfers.ContainsKey(xferID)) 311 if (Transfers.ContainsKey(xferID))
215 RemoveOrDecrement(Transfers[xferID].FileName); 312 {
216 313 Transfers[xferID].done();
217 RemoveXferData(xferID); 314 Transfers.Remove(xferID);
218 } 315 }
219 }
220
221 private void RemoveOrDecrement(string fileName)
222 {
223 // NewFiles must be locked
224
225 if (NewFiles.ContainsKey(fileName))
226 {
227 if (NewFiles[fileName].Count == 1)
228 NewFiles.Remove(fileName);
229 else
230 NewFiles[fileName].Count--;
231 } 316 }
232 } 317 }
233 318
@@ -236,52 +321,124 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
236 public class XferDownLoad 321 public class XferDownLoad
237 { 322 {
238 public IClientAPI Client; 323 public IClientAPI Client;
239 private bool complete;
240 public byte[] Data = new byte[0]; 324 public byte[] Data = new byte[0];
241 public int DataPointer = 0;
242 public string FileName = String.Empty; 325 public string FileName = String.Empty;
243 public uint Packet = 0;
244 public uint Serial = 1;
245 public ulong XferID = 0; 326 public ulong XferID = 0;
246 327 public bool isDeleted = false;
247 public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client) 328
329 private object myLock = new object();
330 private double lastsendTimeMS;
331 private int LastPacket;
332 private int lastBytes;
333 private int lastSentPacket;
334 private int lastAckPacket;
335 private int burstSize;
336 private int retries = 0;
337
338 public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client, int burstsz)
248 { 339 {
249 FileName = fileName; 340 FileName = fileName;
250 Data = data; 341 Data = data;
251 XferID = xferID; 342 XferID = xferID;
252 Client = client; 343 Client = client;
344 burstSize = burstsz;
253 } 345 }
254 346
255 public XferDownLoad() 347 public XferDownLoad()
256 { 348 {
257 } 349 }
258 350
351 public void done()
352 {
353 if(!isDeleted)
354 {
355 Data = new byte[0];
356 isDeleted = true;
357 }
358 }
359
259 /// <summary> 360 /// <summary>
260 /// Start a transfer 361 /// Start a transfer
261 /// </summary> 362 /// </summary>
262 /// <returns>True if the transfer is complete, false if not</returns> 363 /// <returns>True if the transfer is complete, false if not</returns>
263 public bool StartSend() 364 public void StartSend()
264 { 365 {
265 if (Data.Length < 1000) 366 lock(myLock)
266 { 367 {
267 // for now (testing) we only support files under 1000 bytes 368 if(Data.Length == 0) //??
268 byte[] transferData = new byte[Data.Length + 4]; 369 {
269 Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4); 370 LastPacket = 0;
270 Array.Copy(Data, 0, transferData, 4, Data.Length); 371 lastBytes = 0;
271 Client.SendXferPacket(XferID, 0 + 0x80000000, transferData); 372 burstSize = 0;
272 complete = true; 373 }
374 else
375 {
376 // payload of 1024bytes
377 LastPacket = Data.Length >> 10;
378 lastBytes = Data.Length & 0x3ff;
379 if(lastBytes == 0)
380 {
381 lastBytes = 1024;
382 LastPacket--;
383 }
384
385 }
386
387 lastAckPacket = -1;
388 lastSentPacket = -1;
389
390 double now = Util.GetTimeStampMS();
391
392 SendBurst(now);
393 return;
394 }
395 }
396
397 private void SendBurst(double now)
398 {
399 int start = lastAckPacket + 1;
400 int end = start + burstSize;
401 if (end > LastPacket)
402 end = LastPacket;
403 while(start <= end)
404 SendPacket(start++ , now);
405 }
406
407 private void SendPacket(int pkt, double now)
408 {
409 if(pkt > LastPacket)
410 return;
411
412 int pktsize;
413 uint pktid;
414 if (pkt == LastPacket)
415 {
416 pktsize = lastBytes;
417 pktid = (uint)pkt | 0x80000000u;
273 } 418 }
274 else 419 else
275 { 420 {
276 byte[] transferData = new byte[1000 + 4]; 421 pktsize = 1024;
422 pktid = (uint)pkt;
423 }
424
425 byte[] transferData;
426 if(pkt == 0)
427 {
428 transferData = new byte[pktsize + 4];
277 Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4); 429 Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4);
278 Array.Copy(Data, 0, transferData, 4, 1000); 430 Array.Copy(Data, 0, transferData, 4, pktsize);
279 Client.SendXferPacket(XferID, 0, transferData);
280 Packet++;
281 DataPointer = 1000;
282 } 431 }
432 else
433 {
434 transferData = new byte[pktsize];
435 Array.Copy(Data, pkt << 10, transferData, 0, pktsize);
436 }
437
438 Client.SendXferPacket(XferID, pktid, transferData, false);
283 439
284 return complete; 440 lastSentPacket = pkt;
441 lastsendTimeMS = now;
285 } 442 }
286 443
287 /// <summary> 444 /// <summary>
@@ -291,30 +448,46 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
291 /// <returns>True if the transfer is complete, false otherwise</returns> 448 /// <returns>True if the transfer is complete, false otherwise</returns>
292 public bool AckPacket(uint packet) 449 public bool AckPacket(uint packet)
293 { 450 {
294 if (!complete) 451 lock(myLock)
295 { 452 {
296 if ((Data.Length - DataPointer) > 1000) 453 if(isDeleted)
454 return true;
455
456 packet &= 0x7fffffff;
457 if(lastAckPacket < packet)
458 lastAckPacket = (int)packet;
459
460 if(lastAckPacket == LastPacket)
297 { 461 {
298 byte[] transferData = new byte[1000]; 462 done();
299 Array.Copy(Data, DataPointer, transferData, 0, 1000); 463 return true;
300 Client.SendXferPacket(XferID, Packet, transferData);
301 Packet++;
302 DataPointer += 1000;
303 } 464 }
304 else 465 double now = Util.GetTimeStampMS();
466 SendPacket(lastSentPacket + 1, now);
467 return false;
468 }
469 }
470
471 public bool checkTime(double now)
472 {
473 if(Monitor.TryEnter(myLock))
474 {
475 if(!isDeleted)
305 { 476 {
306 byte[] transferData = new byte[Data.Length - DataPointer]; 477 double timeMS = now - lastsendTimeMS;
307 Array.Copy(Data, DataPointer, transferData, 0, Data.Length - DataPointer); 478 if(timeMS > 60000.0)
308 uint endPacket = Packet |= (uint) 0x80000000; 479 done();
309 Client.SendXferPacket(XferID, endPacket, transferData); 480 else if(timeMS > 3500.0 && retries++ < 3)
310 Packet++; 481 {
311 DataPointer += (Data.Length - DataPointer); 482 burstSize >>= 1;
312 483 SendBurst(now);
313 complete = true; 484 }
314 } 485 }
315 }
316 486
317 return complete; 487 Monitor.Exit(myLock);
488 return isDeleted;
489 }
490 return false;
318 } 491 }
319 } 492 }
320 493