diff options
-rw-r--r-- | OpenSim/Framework/Communications/Cache/AssetCache.cs | 118 |
1 files changed, 83 insertions, 35 deletions
diff --git a/OpenSim/Framework/Communications/Cache/AssetCache.cs b/OpenSim/Framework/Communications/Cache/AssetCache.cs index e4c01b3..ca74724 100644 --- a/OpenSim/Framework/Communications/Cache/AssetCache.cs +++ b/OpenSim/Framework/Communications/Cache/AssetCache.cs | |||
@@ -28,12 +28,14 @@ | |||
28 | 28 | ||
29 | using System; | 29 | using System; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.IO; | ||
31 | using System.Reflection; | 32 | using System.Reflection; |
32 | using System.Threading; | 33 | using System.Threading; |
33 | using libsecondlife; | 34 | using libsecondlife; |
34 | using libsecondlife.Packets; | 35 | using libsecondlife.Packets; |
35 | using OpenSim.Framework.Interfaces; | 36 | using OpenSim.Framework.Interfaces; |
36 | using OpenSim.Framework.Types; | 37 | using OpenSim.Framework.Types; |
38 | using OpenSim.Framework.Utilities; | ||
37 | 39 | ||
38 | namespace OpenSim.Framework.Communications.Caches | 40 | namespace OpenSim.Framework.Communications.Caches |
39 | { | 41 | { |
@@ -54,9 +56,15 @@ namespace OpenSim.Framework.Communications.Caches | |||
54 | public Dictionary<LLUUID, AssetRequest> RequestedTextures = new Dictionary<LLUUID, AssetRequest>(); //Textures requested from the asset server | 56 | public Dictionary<LLUUID, AssetRequest> RequestedTextures = new Dictionary<LLUUID, AssetRequest>(); //Textures requested from the asset server |
55 | 57 | ||
56 | public Dictionary<LLUUID, TextureSender> SendingTextures = new Dictionary<LLUUID, TextureSender>(); | 58 | public Dictionary<LLUUID, TextureSender> SendingTextures = new Dictionary<LLUUID, TextureSender>(); |
59 | private BlockingQueue<TextureSender> QueueTextures = new BlockingQueue<TextureSender>(); | ||
60 | |||
61 | private Dictionary<LLUUID, List<LLUUID>> AvatarRecievedTextures = new Dictionary<LLUUID,List<LLUUID>>(); | ||
62 | |||
57 | private IAssetServer _assetServer; | 63 | private IAssetServer _assetServer; |
58 | private Thread _assetCacheThread; | 64 | private Thread _assetCacheThread; |
59 | 65 | ||
66 | private Thread TextureSenderThread; | ||
67 | |||
60 | /// <summary> | 68 | /// <summary> |
61 | /// | 69 | /// |
62 | /// </summary> | 70 | /// </summary> |
@@ -71,6 +79,10 @@ namespace OpenSim.Framework.Communications.Caches | |||
71 | this._assetCacheThread.IsBackground = true; | 79 | this._assetCacheThread.IsBackground = true; |
72 | this._assetCacheThread.Start(); | 80 | this._assetCacheThread.Start(); |
73 | 81 | ||
82 | this.TextureSenderThread = new Thread(new ThreadStart(this.ProcessTextureSenders)); | ||
83 | this.TextureSenderThread.IsBackground = true; | ||
84 | this.TextureSenderThread.Start(); | ||
85 | |||
74 | } | 86 | } |
75 | 87 | ||
76 | public AssetCache(string assetServerDLLName, string assetServerURL, string assetServerKey) | 88 | public AssetCache(string assetServerDLLName, string assetServerURL, string assetServerKey) |
@@ -85,6 +97,9 @@ namespace OpenSim.Framework.Communications.Caches | |||
85 | this._assetCacheThread.IsBackground = true; | 97 | this._assetCacheThread.IsBackground = true; |
86 | this._assetCacheThread.Start(); | 98 | this._assetCacheThread.Start(); |
87 | 99 | ||
100 | this.TextureSenderThread = new Thread(new ThreadStart(this.ProcessTextureSenders)); | ||
101 | this.TextureSenderThread.IsBackground = true; | ||
102 | this.TextureSenderThread.Start(); | ||
88 | } | 103 | } |
89 | 104 | ||
90 | /// <summary> | 105 | /// <summary> |
@@ -165,12 +180,14 @@ namespace OpenSim.Framework.Communications.Caches | |||
165 | req = (AssetRequest)this.TextureRequests[i]; | 180 | req = (AssetRequest)this.TextureRequests[i]; |
166 | if (!this.SendingTextures.ContainsKey(req.ImageInfo.FullID)) | 181 | if (!this.SendingTextures.ContainsKey(req.ImageInfo.FullID)) |
167 | { | 182 | { |
183 | //Console.WriteLine("new texture to send"); | ||
168 | TextureSender sender = new TextureSender(req); | 184 | TextureSender sender = new TextureSender(req); |
169 | sender.OnComplete += this.TextureSent; | 185 | //sender.OnComplete += this.TextureSent; |
170 | lock (this.SendingTextures) | 186 | lock (this.SendingTextures) |
171 | { | 187 | { |
172 | this.SendingTextures.Add(req.ImageInfo.FullID, sender); | 188 | this.SendingTextures.Add(req.ImageInfo.FullID, sender); |
173 | } | 189 | } |
190 | this.QueueTextures.Enqueue(sender); | ||
174 | } | 191 | } |
175 | 192 | ||
176 | } | 193 | } |
@@ -178,6 +195,25 @@ namespace OpenSim.Framework.Communications.Caches | |||
178 | this.TextureRequests.Clear(); | 195 | this.TextureRequests.Clear(); |
179 | } | 196 | } |
180 | 197 | ||
198 | public void ProcessTextureSenders() | ||
199 | { | ||
200 | while (true) | ||
201 | { | ||
202 | TextureSender sender = this.QueueTextures.Dequeue(); | ||
203 | bool finished = sender.SendTexture(); | ||
204 | if (finished) | ||
205 | { | ||
206 | this.TextureSent(sender); | ||
207 | } | ||
208 | else | ||
209 | { | ||
210 | // Console.WriteLine("readding texture"); | ||
211 | this.QueueTextures.Enqueue(sender); | ||
212 | } | ||
213 | } | ||
214 | |||
215 | } | ||
216 | |||
181 | /// <summary> | 217 | /// <summary> |
182 | /// Event handler, called by a TextureSender object to say that texture has been sent | 218 | /// Event handler, called by a TextureSender object to say that texture has been sent |
183 | /// </summary> | 219 | /// </summary> |
@@ -189,6 +225,7 @@ namespace OpenSim.Framework.Communications.Caches | |||
189 | lock (this.SendingTextures) | 225 | lock (this.SendingTextures) |
190 | { | 226 | { |
191 | this.SendingTextures.Remove(sender.request.ImageInfo.FullID); | 227 | this.SendingTextures.Remove(sender.request.ImageInfo.FullID); |
228 | this.AvatarRecievedTextures[sender.request.RequestUser.AgentId].Add(sender.request.ImageInfo.FullID); | ||
192 | } | 229 | } |
193 | } | 230 | } |
194 | } | 231 | } |
@@ -201,8 +238,10 @@ namespace OpenSim.Framework.Communications.Caches | |||
201 | //then add to the correct cache list | 238 | //then add to the correct cache list |
202 | //then check for waiting requests for this asset/texture (in the Requested lists) | 239 | //then check for waiting requests for this asset/texture (in the Requested lists) |
203 | //and move those requests into the Requests list. | 240 | //and move those requests into the Requests list. |
241 | |||
204 | if (IsTexture) | 242 | if (IsTexture) |
205 | { | 243 | { |
244 | // Console.WriteLine("asset recieved from asset server"); | ||
206 | TextureImage image = new TextureImage(asset); | 245 | TextureImage image = new TextureImage(asset); |
207 | this.Textures.Add(image.FullID, image); | 246 | this.Textures.Add(image.FullID, image); |
208 | if (this.RequestedTextures.ContainsKey(image.FullID)) | 247 | if (this.RequestedTextures.ContainsKey(image.FullID)) |
@@ -212,7 +251,7 @@ namespace OpenSim.Framework.Communications.Caches | |||
212 | if (image.Data.LongLength > 600) | 251 | if (image.Data.LongLength > 600) |
213 | { | 252 | { |
214 | //over 600 bytes so split up file | 253 | //over 600 bytes so split up file |
215 | req.NumPackets = 1 + (int)(image.Data.Length - 600 + 999) / 1000; | 254 | req.NumPackets = 1 + (int)(image.Data.Length - 600 ) / 1000; |
216 | } | 255 | } |
217 | else | 256 | else |
218 | { | 257 | { |
@@ -260,7 +299,7 @@ namespace OpenSim.Framework.Communications.Caches | |||
260 | /// <param name="transferRequest"></param> | 299 | /// <param name="transferRequest"></param> |
261 | public void AddAssetRequest(IClientAPI userInfo, TransferRequestPacket transferRequest) | 300 | public void AddAssetRequest(IClientAPI userInfo, TransferRequestPacket transferRequest) |
262 | { | 301 | { |
263 | LLUUID requestID = null; | 302 | LLUUID requestID = null; |
264 | byte source = 2; | 303 | byte source = 2; |
265 | if (transferRequest.TransferInfo.SourceType == 2) | 304 | if (transferRequest.TransferInfo.SourceType == 2) |
266 | { | 305 | { |
@@ -359,7 +398,7 @@ namespace OpenSim.Framework.Communications.Caches | |||
359 | else if (req.AssetRequestSource == 3) | 398 | else if (req.AssetRequestSource == 3) |
360 | { | 399 | { |
361 | Transfer.TransferInfo.Params = req.Params; | 400 | Transfer.TransferInfo.Params = req.Params; |
362 | // Transfer.TransferInfo.Params = new byte[100]; | 401 | // Transfer.TransferInfo.Params = new byte[100]; |
363 | //Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); | 402 | //Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); |
364 | //Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16); | 403 | //Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16); |
365 | } | 404 | } |
@@ -411,7 +450,7 @@ namespace OpenSim.Framework.Communications.Caches | |||
411 | TransferPacket.TransferData.Data = chunk1; | 450 | TransferPacket.TransferData.Data = chunk1; |
412 | TransferPacket.TransferData.Status = 1; | 451 | TransferPacket.TransferData.Status = 1; |
413 | req.RequestUser.OutPacket(TransferPacket); | 452 | req.RequestUser.OutPacket(TransferPacket); |
414 | } | 453 | } |
415 | } | 454 | } |
416 | 455 | ||
417 | } | 456 | } |
@@ -444,8 +483,17 @@ namespace OpenSim.Framework.Communications.Caches | |||
444 | /// <param name="imageID"></param> | 483 | /// <param name="imageID"></param> |
445 | public void AddTextureRequest(IClientAPI userInfo, LLUUID imageID) | 484 | public void AddTextureRequest(IClientAPI userInfo, LLUUID imageID) |
446 | { | 485 | { |
447 | //Console.WriteLine("texture request for " + imageID.ToStringHyphenated()); | 486 | // Console.WriteLine("texture request for " + imageID.ToStringHyphenated()); |
448 | //check to see if texture is in local cache, if not request from asset server | 487 | //check to see if texture is in local cache, if not request from asset server |
488 | if(!this.AvatarRecievedTextures.ContainsKey(userInfo.AgentId)) | ||
489 | { | ||
490 | this.AvatarRecievedTextures.Add(userInfo.AgentId, new List<LLUUID>()); | ||
491 | } | ||
492 | if(this.AvatarRecievedTextures[userInfo.AgentId].Contains(imageID)) | ||
493 | { | ||
494 | //Console.WriteLine(userInfo.AgentId +" is requesting a image( "+ imageID+" that has already been sent to them"); | ||
495 | return; | ||
496 | } | ||
449 | if (!this.Textures.ContainsKey(imageID)) | 497 | if (!this.Textures.ContainsKey(imageID)) |
450 | { | 498 | { |
451 | if (!this.RequestedTextures.ContainsKey(imageID)) | 499 | if (!this.RequestedTextures.ContainsKey(imageID)) |
@@ -472,7 +520,8 @@ namespace OpenSim.Framework.Communications.Caches | |||
472 | if (imag.Data.LongLength > 600) | 520 | if (imag.Data.LongLength > 600) |
473 | { | 521 | { |
474 | //over 600 bytes so split up file | 522 | //over 600 bytes so split up file |
475 | req.NumPackets = 1 + (int)(imag.Data.Length - 600 + 999) / 1000; | 523 | req.NumPackets = 1 + (int)(imag.Data.Length - 600 ) / 1000; |
524 | //Console.WriteLine("texture is " + imag.Data.Length + " which we will send in " +req.NumPackets +" packets"); | ||
476 | } | 525 | } |
477 | else | 526 | else |
478 | { | 527 | { |
@@ -582,37 +631,22 @@ namespace OpenSim.Framework.Communications.Caches | |||
582 | public class TextureSender | 631 | public class TextureSender |
583 | { | 632 | { |
584 | public AssetRequest request; | 633 | public AssetRequest request; |
585 | public event DownloadComplete OnComplete; | 634 | |
586 | Thread m_thread; | ||
587 | public TextureSender(AssetRequest req) | 635 | public TextureSender(AssetRequest req) |
588 | { | 636 | { |
589 | request = req; | 637 | request = req; |
590 | //Console.WriteLine("creating worker thread for texture " + req.ImageInfo.FullID.ToStringHyphenated()); | 638 | |
591 | //Console.WriteLine("texture data length is " + req.ImageInfo.Data.Length); | ||
592 | // Console.WriteLine("in " + req.NumPackets + " packets"); | ||
593 | //ThreadPool.QueueUserWorkItem(new WaitCallback(SendTexture), new object()); | ||
594 | |||
595 | //need some sort of custom threadpool here, as using the .net one, overloads it and stops the handling of incoming packets etc | ||
596 | //but don't really want to create a thread for every texture download | ||
597 | m_thread = new Thread(new ThreadStart(SendTexture)); | ||
598 | m_thread.IsBackground = true; | ||
599 | m_thread.Start(); | ||
600 | } | 639 | } |
601 | 640 | ||
602 | public void SendTexture() | 641 | public bool SendTexture() |
603 | { | 642 | { |
604 | //Console.WriteLine("starting to send sending texture " + request.ImageInfo.FullID.ToStringHyphenated()); | 643 | SendPacket(); |
605 | while (request.PacketCounter != request.NumPackets) | 644 | |
645 | if ((request.PacketCounter > request.NumPackets) |(request.NumPackets ==1)) | ||
606 | { | 646 | { |
607 | SendPacket(); | 647 | return true; |
608 | Thread.Sleep(500); | ||
609 | } | ||
610 | |||
611 | //Console.WriteLine("finished sending texture " + request.ImageInfo.FullID.ToStringHyphenated()); | ||
612 | if (OnComplete != null) | ||
613 | { | ||
614 | OnComplete(this); | ||
615 | } | 648 | } |
649 | return false; | ||
616 | } | 650 | } |
617 | 651 | ||
618 | public void SendPacket() | 652 | public void SendPacket() |
@@ -643,13 +677,14 @@ namespace OpenSim.Framework.Communications.Caches | |||
643 | { | 677 | { |
644 | //more than one packet so split file up | 678 | //more than one packet so split file up |
645 | ImageDataPacket im = new ImageDataPacket(); | 679 | ImageDataPacket im = new ImageDataPacket(); |
646 | im.ImageID.Packets = (ushort)req.NumPackets; | 680 | im.ImageID.Packets = (ushort)(req.NumPackets); |
647 | im.ImageID.ID = req.ImageInfo.FullID; | 681 | im.ImageID.ID = req.ImageInfo.FullID; |
648 | im.ImageID.Size = (uint)req.ImageInfo.Data.Length; | 682 | im.ImageID.Size = (uint)req.ImageInfo.Data.Length; |
649 | im.ImageData.Data = new byte[600]; | 683 | im.ImageData.Data = new byte[600]; |
650 | Array.Copy(req.ImageInfo.Data, 0, im.ImageData.Data, 0, 600); | 684 | Array.Copy(req.ImageInfo.Data, 0, im.ImageData.Data, 0, 600); |
651 | im.ImageID.Codec = 2; | 685 | im.ImageID.Codec = 2; |
652 | req.RequestUser.OutPacket(im); | 686 | req.RequestUser.OutPacket(im); |
687 | //this.SaveAssetToFile("packetheader.dat", im.ImageData.Data); | ||
653 | req.PacketCounter++; | 688 | req.PacketCounter++; |
654 | //req.ImageInfo.last_used = time; | 689 | //req.ImageInfo.last_used = time; |
655 | //System.Console.WriteLine("sent first packet of texture: | 690 | //System.Console.WriteLine("sent first packet of texture: |
@@ -658,23 +693,36 @@ namespace OpenSim.Framework.Communications.Caches | |||
658 | } | 693 | } |
659 | else | 694 | else |
660 | { | 695 | { |
661 | //Console.WriteLine("sending packet" + req.PacketCounter + "for " + req.ImageInfo.FullID.ToStringHyphenated()); | 696 | // Console.WriteLine("sending packet" + req.PacketCounter + "for " + req.ImageInfo.FullID.ToStringHyphenated()); |
662 | //send imagepacket | 697 | //send imagepacket |
663 | //more than one packet so split file up | 698 | //more than one packet so split file up |
664 | ImagePacketPacket im = new ImagePacketPacket(); | 699 | ImagePacketPacket im = new ImagePacketPacket(); |
665 | im.ImageID.Packet = (ushort)req.PacketCounter; | 700 | im.ImageID.Packet = (ushort)(req.PacketCounter); |
666 | im.ImageID.ID = req.ImageInfo.FullID; | 701 | im.ImageID.ID = req.ImageInfo.FullID; |
667 | int size = req.ImageInfo.Data.Length - 600 - 1000 * (req.PacketCounter - 1); | 702 | int size = req.ImageInfo.Data.Length - 600 - (1000 * (req.PacketCounter - 1)); |
668 | if (size > 1000) size = 1000; | 703 | if (size > 1000) size = 1000; |
669 | im.ImageData.Data = new byte[size]; | 704 | im.ImageData.Data = new byte[size]; |
670 | Array.Copy(req.ImageInfo.Data, 600 + 1000 * (req.PacketCounter - 1), im.ImageData.Data, 0, size); | 705 | Array.Copy(req.ImageInfo.Data, 600 + (1000 * (req.PacketCounter - 1)), im.ImageData.Data, 0, size); |
671 | req.RequestUser.OutPacket(im); | 706 | req.RequestUser.OutPacket(im); |
707 | //if (req.PacketCounter == req.NumPackets) | ||
708 | // { | ||
709 | // this.SaveAssetToFile("packet"+req.PacketCounter+".dat", im.ImageData.Data); | ||
710 | //} | ||
672 | req.PacketCounter++; | 711 | req.PacketCounter++; |
673 | //req.ImageInfo.last_used = time; | 712 | //req.ImageInfo.last_used = time; |
674 | //System.Console.WriteLine("sent a packet of texture: "+req.image_info.FullID); | 713 | //System.Console.WriteLine("sent a packet of texture: "+req.image_info.FullID); |
675 | } | 714 | } |
676 | 715 | ||
677 | } | 716 | } |
717 | |||
718 | private void SaveAssetToFile(string filename, byte[] data) | ||
719 | { | ||
720 | FileStream fs = File.Create(filename); | ||
721 | BinaryWriter bw = new BinaryWriter(fs); | ||
722 | bw.Write(data); | ||
723 | bw.Close(); | ||
724 | fs.Close(); | ||
725 | } | ||
678 | } | 726 | } |
679 | } | 727 | } |
680 | } | 728 | } |