aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Communications/Cache/AssetCache.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Communications/Cache/AssetCache.cs')
-rw-r--r--OpenSim/Framework/Communications/Cache/AssetCache.cs465
1 files changed, 230 insertions, 235 deletions
diff --git a/OpenSim/Framework/Communications/Cache/AssetCache.cs b/OpenSim/Framework/Communications/Cache/AssetCache.cs
index 35a0088..ed2fcf4 100644
--- a/OpenSim/Framework/Communications/Cache/AssetCache.cs
+++ b/OpenSim/Framework/Communications/Cache/AssetCache.cs
@@ -1,30 +1,29 @@
1/* 1/*
2* Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3* See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4* 4 *
5* Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7* * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9* * Redistributions in binary form must reproduce the above copyright 9 * * Redistributions in binary form must reproduce the above copyright
10* notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11* documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12* * Neither the name of the OpenSim Project nor the 12 * * Neither the name of the OpenSim Project nor the
13* names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14* derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15* 15 *
16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26* 26 */
27*/
28 27
29using System; 28using System;
30using System.Collections.Generic; 29using System.Collections.Generic;
@@ -131,7 +130,6 @@ namespace OpenSim.Framework.Communications.Cache
131 m_log.InfoFormat("Image data: {0}kb Asset data: {1}kb", 130 m_log.InfoFormat("Image data: {0}kb Asset data: {1}kb",
132 imageBytes / 1024, 131 imageBytes / 1024,
133 assetBytes / 1024); 132 assetBytes / 1024);
134
135 } 133 }
136 134
137 /// <summary> 135 /// <summary>
@@ -179,21 +177,21 @@ namespace OpenSim.Framework.Communications.Cache
179 /// Process the asset queue which holds data which is packeted up and sent 177 /// Process the asset queue which holds data which is packeted up and sent
180 /// directly back to the client. 178 /// directly back to the client.
181 /// </summary> 179 /// </summary>
182 public void RunAssetManager() 180 public void RunAssetManager()
181 {
182 while (true)
183 { 183 {
184 while (true) 184 try
185 { 185 {
186 try 186 ProcessAssetQueue();
187 { 187 Thread.Sleep(500);
188 ProcessAssetQueue(); 188 }
189 Thread.Sleep(500); 189 catch (Exception e)
190 } 190 {
191 catch (Exception e) 191 m_log.Error("[ASSET CACHE]: " + e.ToString());
192 {
193 m_log.Error("[ASSET CACHE]: " + e.ToString());
194 }
195 } 192 }
196 } 193 }
194 }
197 195
198 /// <summary> 196 /// <summary>
199 /// Only get an asset if we already have it in the cache. 197 /// Only get an asset if we already have it in the cache.
@@ -508,19 +506,19 @@ namespace OpenSim.Framework.Communications.Cache
508 // See IAssetReceiver 506 // See IAssetReceiver
509 public void AssetNotFound(LLUUID assetID) 507 public void AssetNotFound(LLUUID assetID)
510 { 508 {
511 // m_log.WarnFormat("[ASSET CACHE]: AssetNotFound for {0}", assetID); 509 // m_log.WarnFormat("[ASSET CACHE]: AssetNotFound for {0}", assetID);
512 510
513 // Notify requesters for this asset 511 // Notify requesters for this asset
514 AssetRequestsList reqList = null; 512 AssetRequestsList reqList = null;
515 lock (RequestLists) 513 lock (RequestLists)
516 { 514 {
517 // m_log.Info("AssetCache: Lock taken on requestLists (AssetNotFound #1)"); 515 // m_log.Info("AssetCache: Lock taken on requestLists (AssetNotFound #1)");
518 if (RequestLists.ContainsKey(assetID)) 516 if (RequestLists.ContainsKey(assetID))
519 { 517 {
520 reqList = RequestLists[assetID]; 518 reqList = RequestLists[assetID];
521 } 519 }
522 } 520 }
523 // m_log.Info("AssetCache: Lock released on requestLists (AssetNotFound #1)"); 521 // m_log.Info("AssetCache: Lock released on requestLists (AssetNotFound #1)");
524 522
525 if (reqList != null) 523 if (reqList != null)
526 { 524 {
@@ -539,205 +537,202 @@ namespace OpenSim.Framework.Communications.Cache
539 req.Callback(assetID, null); 537 req.Callback(assetID, null);
540 } 538 }
541 } 539 }
540 }
542 541
542 /// <summary>
543 /// Calculate the number of packets required to send the asset to the client.
544 /// </summary>
545 /// <param name="data"></param>
546 /// <returns></returns>
547 private int CalculateNumPackets(byte[] data)
548 {
549 const uint m_maxPacketSize = 600;
550 int numPackets = 1;
551
552 if (data.LongLength > m_maxPacketSize)
553 {
554 // over max number of bytes so split up file
555 long restData = data.LongLength - m_maxPacketSize;
556 int restPackets = (int)((restData + m_maxPacketSize - 1) / m_maxPacketSize);
557 numPackets += restPackets;
558 }
559
560 return numPackets;
543 } 561 }
544 562
545 563 /// <summary>
546 /// <summary> 564 /// Make an asset request the result of which will be packeted up and sent directly back to the client.
547 /// Calculate the number of packets required to send the asset to the client. 565 /// </summary>
548 /// </summary> 566 /// <param name="userInfo"></param>
549 /// <param name="data"></param> 567 /// <param name="transferRequest"></param>
550 /// <returns></returns> 568 public void AddAssetRequest(IClientAPI userInfo, TransferRequestPacket transferRequest)
551 private int CalculateNumPackets(byte[] data) 569 {
552 { 570 LLUUID requestID = null;
553 const uint m_maxPacketSize = 600; 571 byte source = 2;
554 int numPackets = 1; 572 if (transferRequest.TransferInfo.SourceType == 2)
555 573 {
556 if (data.LongLength > m_maxPacketSize) 574 //direct asset request
557 { 575 requestID = new LLUUID(transferRequest.TransferInfo.Params, 0);
558 // over max number of bytes so split up file 576 }
559 long restData = data.LongLength - m_maxPacketSize; 577 else if (transferRequest.TransferInfo.SourceType == 3)
560 int restPackets = (int)((restData + m_maxPacketSize - 1) / m_maxPacketSize); 578 {
561 numPackets += restPackets; 579 //inventory asset request
562 } 580 requestID = new LLUUID(transferRequest.TransferInfo.Params, 80);
563 581 source = 3;
564 return numPackets; 582 //Console.WriteLine("asset request " + requestID);
565 } 583 }
566 584 //check to see if asset is in local cache, if not we need to request it from asset server.
567 /// <summary> 585 //Console.WriteLine("asset request " + requestID);
568 /// Make an asset request the result of which will be packeted up and sent directly back to the client. 586 if (!Assets.ContainsKey(requestID))
569 /// </summary> 587 {
570 /// <param name="userInfo"></param> 588 //not found asset
571 /// <param name="transferRequest"></param> 589 // so request from asset server
572 public void AddAssetRequest(IClientAPI userInfo, TransferRequestPacket transferRequest) 590 if (!RequestedAssets.ContainsKey(requestID))
573 { 591 {
574 LLUUID requestID = null; 592 AssetRequest request = new AssetRequest();
575 byte source = 2; 593 request.RequestUser = userInfo;
576 if (transferRequest.TransferInfo.SourceType == 2) 594 request.RequestAssetID = requestID;
577 { 595 request.TransferRequestID = transferRequest.TransferInfo.TransferID;
578 //direct asset request 596 request.AssetRequestSource = source;
579 requestID = new LLUUID(transferRequest.TransferInfo.Params, 0); 597 request.Params = transferRequest.TransferInfo.Params;
580 } 598 RequestedAssets.Add(requestID, request);
581 else if (transferRequest.TransferInfo.SourceType == 3) 599 m_assetServer.RequestAsset(requestID, false);
582 { 600 }
583 //inventory asset request 601 return;
584 requestID = new LLUUID(transferRequest.TransferInfo.Params, 80); 602 }
585 source = 3; 603 //it is in our cache
586 //Console.WriteLine("asset request " + requestID); 604 AssetInfo asset = Assets[requestID];
587 } 605
588 //check to see if asset is in local cache, if not we need to request it from asset server. 606 // add to the AssetRequests list
589 //Console.WriteLine("asset request " + requestID); 607 AssetRequest req = new AssetRequest();
590 if (!Assets.ContainsKey(requestID)) 608 req.RequestUser = userInfo;
591 { 609 req.RequestAssetID = requestID;
592 //not found asset 610 req.TransferRequestID = transferRequest.TransferInfo.TransferID;
593 // so request from asset server 611 req.AssetRequestSource = source;
594 if (!RequestedAssets.ContainsKey(requestID)) 612 req.Params = transferRequest.TransferInfo.Params;
595 { 613 req.AssetInf = asset;
596 AssetRequest request = new AssetRequest(); 614 req.NumPackets = CalculateNumPackets(asset.Data);
597 request.RequestUser = userInfo; 615 AssetRequests.Add(req);
598 request.RequestAssetID = requestID; 616 }
599 request.TransferRequestID = transferRequest.TransferInfo.TransferID;
600 request.AssetRequestSource = source;
601 request.Params = transferRequest.TransferInfo.Params;
602 RequestedAssets.Add(requestID, request);
603 m_assetServer.RequestAsset(requestID, false);
604 }
605 return;
606 }
607 //it is in our cache
608 AssetInfo asset = Assets[requestID];
609
610 // add to the AssetRequests list
611 AssetRequest req = new AssetRequest();
612 req.RequestUser = userInfo;
613 req.RequestAssetID = requestID;
614 req.TransferRequestID = transferRequest.TransferInfo.TransferID;
615 req.AssetRequestSource = source;
616 req.Params = transferRequest.TransferInfo.Params;
617 req.AssetInf = asset;
618 req.NumPackets = CalculateNumPackets(asset.Data);
619 AssetRequests.Add(req);
620 }
621
622 /// <summary>
623 /// Process the asset queue which sends packets directly back to the client.
624 /// </summary>
625 private void ProcessAssetQueue()
626 {
627 //should move the asset downloading to a module, like has been done with texture downloading
628 if (AssetRequests.Count == 0)
629 {
630 //no requests waiting
631 return;
632 }
633 // if less than 5, do all of them
634 int num = Math.Min(5, AssetRequests.Count);
635
636 AssetRequest req;
637 for (int i = 0; i < num; i++)
638 {
639 req = (AssetRequest)AssetRequests[i];
640 //Console.WriteLine("sending asset " + req.RequestAssetID);
641 TransferInfoPacket Transfer = new TransferInfoPacket();
642 Transfer.TransferInfo.ChannelType = 2;
643 Transfer.TransferInfo.Status = 0;
644 Transfer.TransferInfo.TargetType = 0;
645 if (req.AssetRequestSource == 2)
646 {
647 Transfer.TransferInfo.Params = new byte[20];
648 Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
649 int assType = (int)req.AssetInf.Type;
650 Array.Copy(Helpers.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4);
651 }
652 else if (req.AssetRequestSource == 3)
653 {
654 Transfer.TransferInfo.Params = req.Params;
655 // Transfer.TransferInfo.Params = new byte[100];
656 //Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
657 //Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16);
658 }
659 Transfer.TransferInfo.Size = (int)req.AssetInf.Data.Length;
660 Transfer.TransferInfo.TransferID = req.TransferRequestID;
661 req.RequestUser.OutPacket(Transfer, ThrottleOutPacketType.Asset);
662
663 if (req.NumPackets == 1)
664 {
665 TransferPacketPacket TransferPacket = new TransferPacketPacket();
666 TransferPacket.TransferData.Packet = 0;
667 TransferPacket.TransferData.ChannelType = 2;
668 TransferPacket.TransferData.TransferID = req.TransferRequestID;
669 TransferPacket.TransferData.Data = req.AssetInf.Data;
670 TransferPacket.TransferData.Status = 1;
671 req.RequestUser.OutPacket(TransferPacket, ThrottleOutPacketType.Asset);
672 }
673 else
674 {
675 int processedLength = 0;
676 // libsecondlife hardcodes 1500 as the maximum data chunk size
677 int maxChunkSize = 1250;
678 int packetNumber = 0;
679
680 while (processedLength < req.AssetInf.Data.Length)
681 {
682 TransferPacketPacket TransferPacket = new TransferPacketPacket();
683 TransferPacket.TransferData.Packet = packetNumber;
684 TransferPacket.TransferData.ChannelType = 2;
685 TransferPacket.TransferData.TransferID = req.TransferRequestID;
686
687 int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize);
688 byte[] chunk = new byte[chunkSize];
689 Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length);
690
691 TransferPacket.TransferData.Data = chunk;
692
693 // 0 indicates more packets to come, 1 indicates last packet
694 if (req.AssetInf.Data.Length - processedLength > maxChunkSize)
695 {
696 TransferPacket.TransferData.Status = 0;
697 }
698 else
699 {
700 TransferPacket.TransferData.Status = 1;
701 }
702 617
703 req.RequestUser.OutPacket(TransferPacket, ThrottleOutPacketType.Asset); 618 /// <summary>
704 619 /// Process the asset queue which sends packets directly back to the client.
705 processedLength += chunkSize; 620 /// </summary>
706 packetNumber++; 621 private void ProcessAssetQueue()
707 } 622 {
708 } 623 //should move the asset downloading to a module, like has been done with texture downloading
709 } 624 if (AssetRequests.Count == 0)
710 625 {
711 //remove requests that have been completed 626 //no requests waiting
712 for (int i = 0; i < num; i++) 627 return;
713 { 628 }
714 AssetRequests.RemoveAt(0); 629 // if less than 5, do all of them
715 } 630 int num = Math.Min(5, AssetRequests.Count);
716 } 631
717 632 AssetRequest req;
718 public class AssetRequest 633 for (int i = 0; i < num; i++)
719 { 634 {
720 public IClientAPI RequestUser; 635 req = (AssetRequest)AssetRequests[i];
721 public LLUUID RequestAssetID; 636 //Console.WriteLine("sending asset " + req.RequestAssetID);
722 public AssetInfo AssetInf; 637 TransferInfoPacket Transfer = new TransferInfoPacket();
723 public TextureImage ImageInfo; 638 Transfer.TransferInfo.ChannelType = 2;
724 public LLUUID TransferRequestID; 639 Transfer.TransferInfo.Status = 0;
725 public long DataPointer = 0; 640 Transfer.TransferInfo.TargetType = 0;
726 public int NumPackets = 0; 641 if (req.AssetRequestSource == 2)
727 public int PacketCounter = 0; 642 {
728 public bool IsTextureRequest; 643 Transfer.TransferInfo.Params = new byte[20];
729 public byte AssetRequestSource = 2; 644 Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
730 public byte[] Params = null; 645 int assType = (int)req.AssetInf.Type;
731 //public bool AssetInCache; 646 Array.Copy(Helpers.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4);
732 //public int TimeRequested; 647 }
733 public int DiscardLevel = -1; 648 else if (req.AssetRequestSource == 3)
734 649 {
735 public AssetRequest() 650 Transfer.TransferInfo.Params = req.Params;
736 { 651 // Transfer.TransferInfo.Params = new byte[100];
737 } 652 //Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
738 } 653 //Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16);
739 654 }
655 Transfer.TransferInfo.Size = (int)req.AssetInf.Data.Length;
656 Transfer.TransferInfo.TransferID = req.TransferRequestID;
657 req.RequestUser.OutPacket(Transfer, ThrottleOutPacketType.Asset);
740 658
659 if (req.NumPackets == 1)
660 {
661 TransferPacketPacket TransferPacket = new TransferPacketPacket();
662 TransferPacket.TransferData.Packet = 0;
663 TransferPacket.TransferData.ChannelType = 2;
664 TransferPacket.TransferData.TransferID = req.TransferRequestID;
665 TransferPacket.TransferData.Data = req.AssetInf.Data;
666 TransferPacket.TransferData.Status = 1;
667 req.RequestUser.OutPacket(TransferPacket, ThrottleOutPacketType.Asset);
668 }
669 else
670 {
671 int processedLength = 0;
672 // libsecondlife hardcodes 1500 as the maximum data chunk size
673 int maxChunkSize = 1250;
674 int packetNumber = 0;
675
676 while (processedLength < req.AssetInf.Data.Length)
677 {
678 TransferPacketPacket TransferPacket = new TransferPacketPacket();
679 TransferPacket.TransferData.Packet = packetNumber;
680 TransferPacket.TransferData.ChannelType = 2;
681 TransferPacket.TransferData.TransferID = req.TransferRequestID;
682
683 int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize);
684 byte[] chunk = new byte[chunkSize];
685 Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length);
686
687 TransferPacket.TransferData.Data = chunk;
688
689 // 0 indicates more packets to come, 1 indicates last packet
690 if (req.AssetInf.Data.Length - processedLength > maxChunkSize)
691 {
692 TransferPacket.TransferData.Status = 0;
693 }
694 else
695 {
696 TransferPacket.TransferData.Status = 1;
697 }
698
699 req.RequestUser.OutPacket(TransferPacket, ThrottleOutPacketType.Asset);
700
701 processedLength += chunkSize;
702 packetNumber++;
703 }
704 }
705 }
706
707 //remove requests that have been completed
708 for (int i = 0; i < num; i++)
709 {
710 AssetRequests.RemoveAt(0);
711 }
712 }
713
714 public class AssetRequest
715 {
716 public IClientAPI RequestUser;
717 public LLUUID RequestAssetID;
718 public AssetInfo AssetInf;
719 public TextureImage ImageInfo;
720 public LLUUID TransferRequestID;
721 public long DataPointer = 0;
722 public int NumPackets = 0;
723 public int PacketCounter = 0;
724 public bool IsTextureRequest;
725 public byte AssetRequestSource = 2;
726 public byte[] Params = null;
727 //public bool AssetInCache;
728 //public int TimeRequested;
729 public int DiscardLevel = -1;
730
731 public AssetRequest()
732 {
733 }
734 }
735
741 public class AssetInfo : AssetBase 736 public class AssetInfo : AssetBase
742 { 737 {
743 public AssetInfo() 738 public AssetInfo()