more work on texture downloading.

Refractored the TextureDownloadModule (but currently to make debugging easier, it is running as a non shared module, so this results in a instance of this module being created for each region (and a extra thread per region), this will be changed back soon.
Removed the old texture handling/sending code from AssetCache.
A few other small changes/fixes.
This commit is contained in:
MW
2007-12-10 13:27:23 +00:00
parent 081a66d570
commit 611327e104
9 changed files with 298 additions and 439 deletions

View File

@@ -36,8 +36,7 @@ using OpenSim.Framework.Console;
namespace OpenSim.Framework.Communications.Cache
{
public delegate void DownloadComplete(AssetCache.TextureSender sender);
public delegate void AssetRequestCallback(LLUUID assetID, AssetBase asset);
/// <summary>
@@ -57,21 +56,11 @@ namespace OpenSim.Framework.Communications.Cache
public Dictionary<LLUUID, AssetRequest> RequestedTextures = new Dictionary<LLUUID, AssetRequest>();
//Textures requested from the asset server
public Dictionary<LLUUID, TextureSender> SendingTextures = new Dictionary<LLUUID, TextureSender>();
public Dictionary<LLUUID, AssetRequestsList> RequestLists = new Dictionary<LLUUID, AssetRequestsList>();
private BlockingQueue<TextureSender> m_queueTextures = new BlockingQueue<TextureSender>();
private Dictionary<LLUUID, List<LLUUID>> m_avatarReceivedTextures = new Dictionary<LLUUID, List<LLUUID>>();
private Dictionary<LLUUID, Dictionary<LLUUID, int>> m_timesTextureSent =
new Dictionary<LLUUID, Dictionary<LLUUID, int>>();
private IAssetServer m_assetServer;
private Thread m_assetCacheThread;
private Thread m_textureSenderThread;
private LogBase m_log;
/// <summary>
@@ -88,9 +77,7 @@ namespace OpenSim.Framework.Communications.Cache
m_assetCacheThread.IsBackground = true;
m_assetCacheThread.Start();
m_textureSenderThread = new Thread(new ThreadStart(ProcessTextureSenders));
m_textureSenderThread.IsBackground = true;
m_textureSenderThread.Start();
m_log = log;
}
@@ -104,7 +91,6 @@ namespace OpenSim.Framework.Communications.Cache
try
{
ProcessAssetQueue();
ProcessTextureQueue();
Thread.Sleep(500);
}
catch (Exception e)
@@ -188,7 +174,7 @@ namespace OpenSim.Framework.Communications.Cache
if (asset.Type == 0)
{
if(Textures.ContainsKey(asset.FullID))
if (Textures.ContainsKey(asset.FullID))
{
result = "Duplicate ignored.";
}
@@ -250,67 +236,7 @@ namespace OpenSim.Framework.Communications.Cache
return asset;
}
/// <summary>
///
/// </summary>
private void ProcessTextureQueue()
{
if (TextureRequests.Count == 0)
{
//no requests waiting
return;
}
int num;
num = TextureRequests.Count;
AssetRequest req;
for (int i = 0; i < num; i++)
{
req = (AssetRequest) TextureRequests[i];
if (!SendingTextures.ContainsKey(req.ImageInfo.FullID))
{
//Console.WriteLine("new texture to send");
TextureSender sender = new TextureSender(req);
//sender.OnComplete += this.TextureSent;
SendingTextures.Add(req.ImageInfo.FullID, sender);
m_queueTextures.Enqueue(sender);
}
}
TextureRequests.Clear();
}
public void ProcessTextureSenders()
{
while (true)
{
TextureSender sender = m_queueTextures.Dequeue();
bool finished = sender.SendTexture();
if (finished)
{
TextureSent(sender);
}
else
{
// Console.WriteLine("readding texture");
m_queueTextures.Enqueue(sender);
}
}
}
/// <summary>
/// Event handler, called by a TextureSender object to say that texture has been sent
/// </summary>
/// <param name="sender"></param>
public void TextureSent(TextureSender sender)
{
if (SendingTextures.ContainsKey(sender.request.ImageInfo.FullID))
{
SendingTextures.Remove(sender.request.ImageInfo.FullID);
// this.m_avatarReceivedTextures[sender.request.RequestUser.AgentId].Add(sender.request.ImageInfo.FullID);
}
}
public void AssetReceived(AssetBase asset, bool IsTexture)
{
@@ -354,7 +280,7 @@ namespace OpenSim.Framework.Communications.Cache
if (assetInf.Data.LongLength > 600)
{
//over 600 bytes so split up file
req.NumPackets = 1 + (int) (assetInf.Data.Length - 600 + 999)/1000;
req.NumPackets = 1 + (int)(assetInf.Data.Length - 600 + 999) / 1000;
}
else
{
@@ -400,6 +326,20 @@ namespace OpenSim.Framework.Communications.Cache
//}
}
private int CalculateNumPackets(int length)
{
int numPackets = 1;
if (length > 600)
{
//over 600 bytes so split up file
int restData = (length - 600);
int restPackets = ((restData + 999) / 1000);
numPackets = 1 + restPackets;
}
return numPackets;
}
#region Assets
/// <summary>
@@ -458,7 +398,7 @@ namespace OpenSim.Framework.Communications.Cache
if (asset.Data.LongLength > 600)
{
//over 600 bytes so split up file
req.NumPackets = 1 + (int) (asset.Data.Length - 600 + 999)/1000;
req.NumPackets = 1 + (int)(asset.Data.Length - 600 + 999) / 1000;
}
else
{
@@ -473,6 +413,7 @@ namespace OpenSim.Framework.Communications.Cache
/// </summary>
private void ProcessAssetQueue()
{
//should move the asset downloading to a module, like has been done with texture downloading
if (AssetRequests.Count == 0)
{
//no requests waiting
@@ -492,7 +433,7 @@ namespace OpenSim.Framework.Communications.Cache
AssetRequest req;
for (int i = 0; i < num; i++)
{
req = (AssetRequest) AssetRequests[i];
req = (AssetRequest)AssetRequests[i];
//Console.WriteLine("sending asset " + req.RequestAssetID);
TransferInfoPacket Transfer = new TransferInfoPacket();
Transfer.TransferInfo.ChannelType = 2;
@@ -502,7 +443,7 @@ namespace OpenSim.Framework.Communications.Cache
{
Transfer.TransferInfo.Params = new byte[20];
Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
int assType = (int) req.AssetInf.Type;
int assType = (int)req.AssetInf.Type;
Array.Copy(Helpers.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4);
}
else if (req.AssetRequestSource == 3)
@@ -512,9 +453,9 @@ namespace OpenSim.Framework.Communications.Cache
//Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
//Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16);
}
Transfer.TransferInfo.Size = (int) req.AssetInf.Data.Length;
Transfer.TransferInfo.Size = (int)req.AssetInf.Data.Length;
Transfer.TransferInfo.TransferID = req.TransferRequestID;
req.RequestUser.OutPacket(Transfer,ThrottleOutPacketType.Asset);
req.RequestUser.OutPacket(Transfer, ThrottleOutPacketType.Asset);
if (req.NumPackets == 1)
{
@@ -573,79 +514,6 @@ namespace OpenSim.Framework.Communications.Cache
#endregion
#region Textures
/// <summary>
///
/// </summary>
/// <param name="userInfo"></param>
/// <param name="imageID"></param>
public void AddTextureRequest(IClientAPI userInfo, LLUUID imageID, uint packetNumber, int discard)
{
// System.Console.WriteLine("texture request for " + imageID.ToStringHyphenated() + " packetnumber= " + packetNumber);
//check to see if texture is in local cache, if not request from asset server
if (!m_avatarReceivedTextures.ContainsKey(userInfo.AgentId))
{
m_avatarReceivedTextures.Add(userInfo.AgentId, new List<LLUUID>());
}
/* if(this.m_avatarReceivedTextures[userInfo.AgentId].Contains(imageID))
{
//Console.WriteLine(userInfo.AgentId +" is requesting a image( "+ imageID+" that has already been sent to them");
return;
}*/
if (!Textures.ContainsKey(imageID))
{
if (!RequestedTextures.ContainsKey(imageID))
{
//not is cache so request from asset server
AssetRequest request = new AssetRequest();
request.RequestUser = userInfo;
request.RequestAssetID = imageID;
request.IsTextureRequest = true;
request.DiscardLevel = discard;
RequestedTextures.Add(imageID, request);
m_assetServer.RequestAsset(imageID, true);
}
return;
}
// System.Console.WriteLine("texture already in cache");
TextureImage imag = Textures[imageID];
AssetRequest req = new AssetRequest();
req.RequestUser = userInfo;
req.RequestAssetID = imageID;
req.IsTextureRequest = true;
req.ImageInfo = imag;
req.DiscardLevel = discard;
req.NumPackets = CalculateNumPackets(imag.Data.Length);
if (packetNumber != 0)
{
req.PacketCounter = (int) packetNumber;
}
TextureRequests.Add(req);
}
private int CalculateNumPackets(int length)
{
int numPackets = 1;
if (length > 600)
{
//over 600 bytes so split up file
int restData = (length - 600);
int restPackets = ((restData+999)/1000);
numPackets = 1 + restPackets;
}
return numPackets;
}
#endregion
public class AssetRequest
{
public IClientAPI RequestUser;
@@ -702,123 +570,28 @@ namespace OpenSim.Framework.Communications.Cache
}
}
public class TextureSender
public class AssetRequestsList
{
public AssetRequest request;
private int counter = 0;
public LLUUID AssetID;
public List<NewAssetRequest> Requests = new List<NewAssetRequest>();
public TextureSender(AssetRequest req)
public AssetRequestsList(LLUUID assetID)
{
request = req;
}
public bool SendTexture()
{
SendPacket();
counter++;
if ((request.PacketCounter >= request.NumPackets) || counter > 100 || (request.NumPackets == 1) ||
(request.DiscardLevel == -1))
{
return true;
}
return false;
}
public void SendPacket()
{
AssetRequest req = request;
//Console.WriteLine("sending " + req.ImageInfo.FullID);
if (req.PacketCounter == 0)
{
//first time for this request so send imagedata packet
if (req.NumPackets == 1)
{
//Console.WriteLine("only one packet so send whole file");
ImageDataPacket im = new ImageDataPacket();
im.Header.Reliable = false;
im.ImageID.Packets = 1;
im.ImageID.ID = req.ImageInfo.FullID;
im.ImageID.Size = (uint) req.ImageInfo.Data.Length;
im.ImageData.Data = req.ImageInfo.Data;
im.ImageID.Codec = 2;
req.RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
req.PacketCounter++;
//req.ImageInfo.l= time;
//System.Console.WriteLine("sent texture: " + req.ImageInfo.FullID);
//Console.WriteLine("sending single packet for " + req.ImageInfo.FullID.ToStringHyphenated());
}
else
{
//more than one packet so split file up
ImageDataPacket im = new ImageDataPacket();
im.Header.Reliable = false;
im.ImageID.Packets = (ushort) (req.NumPackets);
im.ImageID.ID = req.ImageInfo.FullID;
im.ImageID.Size = (uint) req.ImageInfo.Data.Length;
im.ImageData.Data = new byte[600];
Array.Copy(req.ImageInfo.Data, 0, im.ImageData.Data, 0, 600);
im.ImageID.Codec = 2;
req.RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
req.PacketCounter++;
//req.ImageInfo.last_used = time;
//System.Console.WriteLine("sent first packet of texture: " + req.ImageInfo.FullID);
//Console.WriteLine("sending packet 1 for " + req.ImageInfo.FullID.ToStringHyphenated());
}
}
else
{
//Console.WriteLine("sending packet " + req.PacketCounter + " for " + req.ImageInfo.FullID.ToStringHyphenated());
//send imagepacket
//more than one packet so split file up
ImagePacketPacket im = new ImagePacketPacket();
im.Header.Reliable = false;
im.ImageID.Packet = (ushort) (req.PacketCounter);
im.ImageID.ID = req.ImageInfo.FullID;
int size = req.ImageInfo.Data.Length - 600 - (1000*(req.PacketCounter - 1));
if (size > 1000) size = 1000;
//Console.WriteLine("length= {0} counter= {1} size= {2}",req.ImageInfo.Data.Length, req.PacketCounter, size);
im.ImageData.Data = new byte[size];
Array.Copy(req.ImageInfo.Data, 600 + (1000*(req.PacketCounter - 1)), im.ImageData.Data, 0, size);
req.RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
req.PacketCounter++;
//req.ImageInfo.last_used = time;
//System.Console.WriteLine("sent a packet of texture: "+req.ImageInfo.FullID);
}
}
private void SaveAssetToFile(string filename, byte[] data)
{
FileStream fs = File.Create(filename);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(data);
bw.Close();
fs.Close();
AssetID = assetID;
}
}
}
public class AssetRequestsList
{
public LLUUID AssetID;
public List<NewAssetRequest> Requests = new List<NewAssetRequest>();
public AssetRequestsList(LLUUID assetID)
public class NewAssetRequest
{
AssetID = assetID;
}
}
public LLUUID AssetID;
public AssetRequestCallback Callback;
public class NewAssetRequest
{
public LLUUID AssetID;
public AssetRequestCallback Callback;
public NewAssetRequest(LLUUID assetID, AssetRequestCallback callback)
{
AssetID = assetID;
Callback = callback;
public NewAssetRequest(LLUUID assetID, AssetRequestCallback callback)
{
AssetID = assetID;
Callback = callback;
}
}
}
}

View File

@@ -83,7 +83,7 @@ namespace OpenSim.Framework.Communications.Cache
}
public void HandleUDPUploadRequest(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type,
byte[] data, bool storeLocal)
byte[] data, bool storeLocal, bool tempFile)
{
// Console.WriteLine("asset upload of " + assetID);
AgentAssetTransactions transactions = GetUserTransActions(remoteClient.AgentId);
@@ -92,7 +92,7 @@ namespace OpenSim.Framework.Communications.Cache
AgentAssetTransactions.AssetXferUploader uploader = transactions.RequestXferUploader(transaction);
if (uploader != null)
{
uploader.Initialise(remoteClient, assetID, transaction, type, data, storeLocal);
uploader.Initialise(remoteClient, assetID, transaction, type, data, storeLocal, tempFile);
}
}
}

View File

@@ -113,66 +113,6 @@ namespace OpenSim.Framework.Communications.Cache
}
// Nested Types
public class AssetCapsUploader
{
// Fields
private BaseHttpServer httpListener;
private LLUUID inventoryItemID;
private string m_assetDescription = "";
private string m_assetName = "";
private LLUUID m_folderID;
private LLUUID newAssetID;
private bool m_dumpImageToFile;
private string uploaderPath = "";
// Events
public event UpLoadedAsset OnUpLoad;
// Methods
public void Initialise(string assetName, string assetDescription, LLUUID assetID, LLUUID inventoryItem,
LLUUID folderID, string path, BaseHttpServer httpServer, bool dumpImageToFile)
{
m_assetName = assetName;
m_assetDescription = assetDescription;
m_folderID = folderID;
newAssetID = assetID;
inventoryItemID = inventoryItem;
uploaderPath = path;
httpListener = httpServer;
m_dumpImageToFile = dumpImageToFile;
}
private void SaveImageToFile(string filename, byte[] data)
{
FileStream output = File.Create(filename);
BinaryWriter writer = new BinaryWriter(output);
writer.Write(data);
writer.Close();
output.Close();
}
public string uploaderCaps(byte[] data, string path, string param)
{
LLUUID inventoryItemID = this.inventoryItemID;
string text = "";
LLSDAssetUploadComplete complete = new LLSDAssetUploadComplete();
complete.new_asset = newAssetID.ToStringHyphenated();
complete.new_inventory_item = inventoryItemID;
complete.state = "complete";
text = LLSDHelpers.SerialiseLLSDReply(complete);
httpListener.RemoveStreamHandler("POST", uploaderPath);
if (m_dumpImageToFile)
{
SaveImageToFile(m_assetName + ".jp2", data);
}
if (OnUpLoad != null)
{
OnUpLoad(m_assetName, "description", newAssetID, inventoryItemID, LLUUID.Zero, data, "", "");
}
return text;
}
}
public class AssetXferUploader
{
// Fields
@@ -230,7 +170,7 @@ namespace OpenSim.Framework.Communications.Cache
}
public void Initialise(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type, byte[] data,
bool storeLocal)
bool storeLocal, bool tempFile)
{
ourClient = remoteClient;
Asset = new AssetBase();
@@ -240,6 +180,9 @@ namespace OpenSim.Framework.Communications.Cache
Asset.Data = data;
Asset.Name = "blank";
Asset.Description = "empty";
Asset.Local = storeLocal;
Asset.Temporary = tempFile;
TransactionID = transaction;
m_storeLocal = storeLocal;
if (Asset.Data.Length > 2)
@@ -368,6 +311,67 @@ namespace OpenSim.Framework.Communications.Cache
}
}
#region Nested Classes currently not in use (waiting for them to be enabled)
public class AssetCapsUploader
{
// Fields
private BaseHttpServer httpListener;
private LLUUID inventoryItemID;
private string m_assetDescription = "";
private string m_assetName = "";
private LLUUID m_folderID;
private LLUUID newAssetID;
private bool m_dumpImageToFile;
private string uploaderPath = "";
// Events
public event UpLoadedAsset OnUpLoad;
// Methods
public void Initialise(string assetName, string assetDescription, LLUUID assetID, LLUUID inventoryItem,
LLUUID folderID, string path, BaseHttpServer httpServer, bool dumpImageToFile)
{
m_assetName = assetName;
m_assetDescription = assetDescription;
m_folderID = folderID;
newAssetID = assetID;
inventoryItemID = inventoryItem;
uploaderPath = path;
httpListener = httpServer;
m_dumpImageToFile = dumpImageToFile;
}
private void SaveImageToFile(string filename, byte[] data)
{
FileStream output = File.Create(filename);
BinaryWriter writer = new BinaryWriter(output);
writer.Write(data);
writer.Close();
output.Close();
}
public string uploaderCaps(byte[] data, string path, string param)
{
LLUUID inventoryItemID = this.inventoryItemID;
string text = "";
LLSDAssetUploadComplete complete = new LLSDAssetUploadComplete();
complete.new_asset = newAssetID.ToStringHyphenated();
complete.new_inventory_item = inventoryItemID;
complete.state = "complete";
text = LLSDHelpers.SerialiseLLSDReply(complete);
httpListener.RemoveStreamHandler("POST", uploaderPath);
if (m_dumpImageToFile)
{
SaveImageToFile(m_assetName + ".jp2", data);
}
if (OnUpLoad != null)
{
OnUpLoad(m_assetName, "description", newAssetID, inventoryItemID, LLUUID.Zero, data, "", "");
}
return text;
}
}
public class NoteCardCapsUpdate
{
// Fields
@@ -420,5 +424,6 @@ namespace OpenSim.Framework.Communications.Cache
return text;
}
}
#endregion
}
}

View File

@@ -10,7 +10,7 @@ using System.Text;
namespace OpenSim.Region.Capabilities
{
/// <summary>
///
/// Borrowed from (a older version of ) libsl for now, as their new llsd code doesn't work we our decoding code.
/// </summary>
public static class LLSD
{

View File

@@ -157,6 +157,13 @@ namespace OpenSim.Framework
protected LLUUID m_requestedAssetID;
private sbyte m_discardLevel;
private uint m_packetNumber;
private float m_priority;
public float Priority
{
get { return m_priority; }
set { m_priority = value; }
}
/// <summary>
///
@@ -348,7 +355,7 @@ namespace OpenSim.Framework
public delegate void RemoveTaskInventory(IClientAPI remoteClient, LLUUID itemID, uint localID);
public delegate void UDPAssetUploadRequest(
IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type, byte[] data, bool storeLocal);
IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type, byte[] data, bool storeLocal, bool tempFile);
public delegate void XferReceive(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data);