* Trying to address TextureSender issues

* The BlockingQueue exposes Contains so we can make sure we don't add a TextureSender to the queue if there's already one present
* introduced some TryGetValue and various code convention stuff
afrisby
lbsa71 2008-01-02 09:07:11 +00:00
parent e678056e13
commit 4b4ee98070
6 changed files with 91 additions and 78 deletions

View File

@ -32,27 +32,34 @@ namespace OpenSim.Framework
{ {
public class BlockingQueue<T> public class BlockingQueue<T>
{ {
private Queue<T> _queue = new Queue<T>(); private readonly Queue<T> m_queue = new Queue<T>();
private object _queueSync = new object(); private readonly object m_queueSync = new object();
public void Enqueue(T value) public void Enqueue(T value)
{ {
lock (_queueSync) lock (m_queueSync)
{ {
_queue.Enqueue(value); m_queue.Enqueue(value);
Monitor.Pulse(_queueSync); Monitor.Pulse(m_queueSync);
} }
} }
public T Dequeue() public T Dequeue()
{ {
lock (_queueSync) lock (m_queueSync)
{ {
if (_queue.Count < 1) if (m_queue.Count < 1)
Monitor.Wait(_queueSync); {
Monitor.Wait(m_queueSync);
}
return _queue.Dequeue(); return m_queue.Dequeue();
} }
} }
public bool Contains(T item)
{
return m_queue.Contains(item);
}
} }
} }

View File

@ -56,10 +56,10 @@ namespace OpenSim.Framework.Communications.Cache
public Dictionary<LLUUID, AssetRequestsList> RequestLists = new Dictionary<LLUUID, AssetRequestsList>(); public Dictionary<LLUUID, AssetRequestsList> RequestLists = new Dictionary<LLUUID, AssetRequestsList>();
private IAssetServer m_assetServer; private readonly IAssetServer m_assetServer;
private Thread m_assetCacheThread; private readonly Thread m_assetCacheThread;
private LogBase m_log; private readonly LogBase m_log;
/// <summary> /// <summary>
/// ///

View File

@ -37,11 +37,11 @@ namespace OpenSim.Framework.Communications.Cache
{ {
public abstract class AssetServerBase : IAssetServer public abstract class AssetServerBase : IAssetServer
{ {
protected IAssetReceiver _receiver; protected IAssetReceiver m_receiver;
protected BlockingQueue<AssetRequest> _assetRequests; protected BlockingQueue<AssetRequest> m_assetRequests;
protected Thread _localAssetServerThread; protected Thread m_localAssetServerThread;
protected IAssetProvider m_assetProviderPlugin; protected IAssetProvider m_assetProvider;
protected object syncLock = new object(); protected object m_syncLock = new object();
// Temporarily hardcoded - should be a plugin // Temporarily hardcoded - should be a plugin
protected IAssetLoader assetLoader = new AssetLoaderFileSystem(); protected IAssetLoader assetLoader = new AssetLoaderFileSystem();
@ -71,14 +71,14 @@ namespace OpenSim.Framework.Communications.Cache
MainLog.Instance.Verbose( MainLog.Instance.Verbose(
"ASSET", "Asset {0} received from asset server", req.AssetID); "ASSET", "Asset {0} received from asset server", req.AssetID);
_receiver.AssetReceived(asset, req.IsTexture); m_receiver.AssetReceived(asset, req.IsTexture);
} }
else else
{ {
MainLog.Instance.Error( MainLog.Instance.Error(
"ASSET", "Asset {0} not found by asset server", req.AssetID); "ASSET", "Asset {0} not found by asset server", req.AssetID);
_receiver.AssetNotFound(req.AssetID); m_receiver.AssetNotFound(req.AssetID);
} }
} }
@ -95,11 +95,11 @@ namespace OpenSim.Framework.Communications.Cache
public AssetServerBase() public AssetServerBase()
{ {
MainLog.Instance.Verbose("ASSETSERVER", "Starting asset storage system"); MainLog.Instance.Verbose("ASSETSERVER", "Starting asset storage system");
_assetRequests = new BlockingQueue<AssetRequest>(); m_assetRequests = new BlockingQueue<AssetRequest>();
_localAssetServerThread = new Thread(RunRequests); m_localAssetServerThread = new Thread(RunRequests);
_localAssetServerThread.IsBackground = true; m_localAssetServerThread.IsBackground = true;
_localAssetServerThread.Start(); m_localAssetServerThread.Start();
} }
private void RunRequests() private void RunRequests()
@ -108,7 +108,7 @@ namespace OpenSim.Framework.Communications.Cache
{ {
try try
{ {
AssetRequest req = _assetRequests.Dequeue(); AssetRequest req = m_assetRequests.Dequeue();
ProcessRequest(req); ProcessRequest(req);
} }
@ -121,7 +121,7 @@ namespace OpenSim.Framework.Communications.Cache
public void SetReceiver(IAssetReceiver receiver) public void SetReceiver(IAssetReceiver receiver)
{ {
_receiver = receiver; m_receiver = receiver;
} }
public void RequestAsset(LLUUID assetID, bool isTexture) public void RequestAsset(LLUUID assetID, bool isTexture)
@ -129,23 +129,23 @@ namespace OpenSim.Framework.Communications.Cache
AssetRequest req = new AssetRequest(); AssetRequest req = new AssetRequest();
req.AssetID = assetID; req.AssetID = assetID;
req.IsTexture = isTexture; req.IsTexture = isTexture;
_assetRequests.Enqueue(req); m_assetRequests.Enqueue(req);
MainLog.Instance.Verbose("ASSET", "Added {0} to request queue", assetID); MainLog.Instance.Verbose("ASSET", "Added {0} to request queue", assetID);
} }
public virtual void UpdateAsset(AssetBase asset) public virtual void UpdateAsset(AssetBase asset)
{ {
lock (syncLock) lock (m_syncLock)
{ {
m_assetProviderPlugin.UpdateAsset(asset); m_assetProvider.UpdateAsset(asset);
m_assetProviderPlugin.CommitAssets(); m_assetProvider.CommitAssets();
} }
} }
public void StoreAndCommitAsset(AssetBase asset) public void StoreAndCommitAsset(AssetBase asset)
{ {
lock (syncLock) lock (m_syncLock)
{ {
StoreAsset(asset); StoreAsset(asset);
CommitAssets(); CommitAssets();
@ -154,7 +154,7 @@ namespace OpenSim.Framework.Communications.Cache
public virtual void Close() public virtual void Close()
{ {
_localAssetServerThread.Abort(); m_localAssetServerThread.Abort();
} }
public void SetServerInfo(string ServerUrl, string ServerKey) public void SetServerInfo(string ServerUrl, string ServerKey)

View File

@ -40,7 +40,7 @@ namespace OpenSim.Framework.Communications.Cache
public SQLAssetServer(IAssetProvider assetProvider) public SQLAssetServer(IAssetProvider assetProvider)
{ {
m_assetProviderPlugin = assetProvider; m_assetProvider = assetProvider;
} }
public void AddPlugin(string FileName) public void AddPlugin(string FileName)
@ -58,12 +58,12 @@ namespace OpenSim.Framework.Communications.Cache
{ {
IAssetProvider plug = IAssetProvider plug =
(IAssetProvider) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); (IAssetProvider) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));
m_assetProviderPlugin = plug; m_assetProvider = plug;
m_assetProviderPlugin.Initialise(); m_assetProvider.Initialise();
MainLog.Instance.Verbose("AssetStorage", MainLog.Instance.Verbose("AssetStorage",
"Added " + m_assetProviderPlugin.Name + " " + "Added " + m_assetProvider.Name + " " +
m_assetProviderPlugin.Version); m_assetProvider.Version);
} }
} }
} }
@ -74,15 +74,15 @@ namespace OpenSim.Framework.Communications.Cache
{ {
base.Close(); base.Close();
m_assetProviderPlugin.CommitAssets(); m_assetProvider.CommitAssets();
} }
protected override AssetBase GetAsset(AssetRequest req) protected override AssetBase GetAsset(AssetRequest req)
{ {
AssetBase asset; AssetBase asset;
lock (syncLock) lock (m_syncLock)
{ {
asset = m_assetProviderPlugin.FetchAsset(req.AssetID); asset = m_assetProvider.FetchAsset(req.AssetID);
} }
return asset; return asset;
@ -90,12 +90,12 @@ namespace OpenSim.Framework.Communications.Cache
protected override void StoreAsset(AssetBase asset) protected override void StoreAsset(AssetBase asset)
{ {
m_assetProviderPlugin.CreateAsset(asset); m_assetProvider.CreateAsset(asset);
} }
protected override void CommitAssets() protected override void CommitAssets()
{ {
m_assetProviderPlugin.CommitAssets(); m_assetProvider.CommitAssets();
} }
} }
} }

View File

@ -2973,7 +2973,6 @@ namespace OpenSim.Region.ClientStack
//Console.WriteLine("image request: " + Pack.ToString()); //Console.WriteLine("image request: " + Pack.ToString());
for (int i = 0; i < imageRequest.RequestImage.Length; i++) for (int i = 0; i < imageRequest.RequestImage.Length; i++)
{ {
// still working on the Texture download module so for now using old method
if (OnRequestTexture != null) if (OnRequestTexture != null)
{ {
TextureRequestArgs args = new TextureRequestArgs(); TextureRequestArgs args = new TextureRequestArgs();
@ -2984,10 +2983,6 @@ namespace OpenSim.Region.ClientStack
OnRequestTexture(this, args); OnRequestTexture(this, args);
} }
// m_assetCache.AddTextureRequest(this, imageRequest.RequestImage[i].Image,
// imageRequest.RequestImage[i].Packet,
// imageRequest.RequestImage[i].DiscardLevel);
} }
break; break;
case PacketType.TransferRequest: case PacketType.TransferRequest:

View File

@ -47,7 +47,7 @@ namespace OpenSim.Region.Environment.Modules
private Scene m_scene; private Scene m_scene;
private List<Scene> m_scenes = new List<Scene>(); private List<Scene> m_scenes = new List<Scene>();
private BlockingQueue<TextureSender> QueueSenders = new BlockingQueue<TextureSender>(); private readonly BlockingQueue<TextureSender> m_queueSenders = new BlockingQueue<TextureSender>();
private Dictionary<LLUUID, UserTextureDownloadService> m_userTextureServices = private Dictionary<LLUUID, UserTextureDownloadService> m_userTextureServices =
new Dictionary<LLUUID, UserTextureDownloadService>(); new Dictionary<LLUUID, UserTextureDownloadService>();
@ -108,7 +108,7 @@ namespace OpenSim.Region.Environment.Modules
return true; return true;
} }
textureService = new UserTextureDownloadService(m_scene, QueueSenders); textureService = new UserTextureDownloadService(m_scene, m_queueSenders);
m_userTextureServices.Add(userID, textureService); m_userTextureServices.Add(userID, textureService);
return true; return true;
} }
@ -128,7 +128,7 @@ namespace OpenSim.Region.Environment.Modules
{ {
while (true) while (true)
{ {
TextureSender sender = QueueSenders.Dequeue(); TextureSender sender = m_queueSenders.Dequeue();
if (sender.Cancel) if (sender.Cancel)
{ {
TextureSent(sender); TextureSent(sender);
@ -142,7 +142,7 @@ namespace OpenSim.Region.Environment.Modules
} }
else else
{ {
QueueSenders.Enqueue(sender); m_queueSenders.Enqueue(sender);
} }
} }
} }
@ -155,11 +155,9 @@ namespace OpenSim.Region.Environment.Modules
public class UserTextureDownloadService public class UserTextureDownloadService
{ {
private Dictionary<LLUUID, TextureSender> m_textureSenders = new Dictionary<LLUUID, TextureSender>(); private readonly Dictionary<LLUUID, TextureSender> m_textureSenders = new Dictionary<LLUUID, TextureSender>();
private readonly BlockingQueue<TextureSender> m_sharedSendersQueue;
private BlockingQueue<TextureSender> m_sharedSendersQueue; private readonly Scene m_scene;
private Scene m_scene;
public UserTextureDownloadService(Scene scene, BlockingQueue<TextureSender> sharedQueue) public UserTextureDownloadService(Scene scene, BlockingQueue<TextureSender> sharedQueue)
{ {
@ -169,38 +167,45 @@ namespace OpenSim.Region.Environment.Modules
public void HandleTextureRequest(IClientAPI client, TextureRequestArgs e) public void HandleTextureRequest(IClientAPI client, TextureRequestArgs e)
{ {
TextureSender textureSender;
//TODO: should be working out the data size/ number of packets to be sent for each discard level //TODO: should be working out the data size/ number of packets to be sent for each discard level
if ((e.DiscardLevel >= 0) || (e.Priority != 0)) if ((e.DiscardLevel >= 0) || (e.Priority != 0))
{ {
lock (m_textureSenders) lock (m_textureSenders)
{ {
if (!m_textureSenders.ContainsKey(e.RequestedAssetID)) if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender))
{
textureSender.UpdateRequest(e.DiscardLevel, e.PacketNumber);
textureSender.counter = 0;
if ((textureSender.ImageLoaded) &&
(textureSender.Sending == false))
{
textureSender.Sending = true;
if (!m_sharedSendersQueue.Contains(textureSender))
{
m_sharedSendersQueue.Enqueue(textureSender);
}
}
}
else
{ {
TextureSender requestHandler = TextureSender requestHandler =
new TextureSender(client, e.RequestedAssetID, e.DiscardLevel, e.PacketNumber); new TextureSender(client, e.RequestedAssetID, e.DiscardLevel, e.PacketNumber);
m_textureSenders.Add(e.RequestedAssetID, requestHandler); m_textureSenders.Add(e.RequestedAssetID, requestHandler);
m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback); m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback);
} }
else
{
m_textureSenders[e.RequestedAssetID].UpdateRequest(e.DiscardLevel, e.PacketNumber);
m_textureSenders[e.RequestedAssetID].counter = 0;
if ((m_textureSenders[e.RequestedAssetID].ImageLoaded) &&
(m_textureSenders[e.RequestedAssetID].Sending == false))
{
m_textureSenders[e.RequestedAssetID].Sending = true;
m_sharedSendersQueue.Enqueue(m_textureSenders[e.RequestedAssetID]);
}
}
} }
} }
else else
{ {
lock (m_textureSenders) lock (m_textureSenders)
{ {
if (m_textureSenders.ContainsKey(e.RequestedAssetID)) if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender))
{ {
m_textureSenders[e.RequestedAssetID].Cancel = true; textureSender.Cancel = true;
} }
} }
} }
@ -210,19 +215,25 @@ namespace OpenSim.Region.Environment.Modules
{ {
lock (m_textureSenders) lock (m_textureSenders)
{ {
if (m_textureSenders.ContainsKey(textureID)) TextureSender textureSender;
if (m_textureSenders.TryGetValue(textureID, out textureSender))
{ {
if (!m_textureSenders[textureID].ImageLoaded) if (!textureSender.ImageLoaded)
{ {
m_textureSenders[textureID].TextureReceived(asset); textureSender.TextureReceived(asset);
m_textureSenders[textureID].Sending = true; textureSender.Sending = true;
m_textureSenders[textureID].counter = 0; textureSender.counter = 0;
m_sharedSendersQueue.Enqueue(m_textureSenders[textureID]);
if (!m_sharedSendersQueue.Contains(textureSender))
{
m_sharedSendersQueue.Enqueue(textureSender);
}
} }
} }
else else
{ {
// Got a texture with no sender object to handle it, this shouldn't happen throw new Exception("Got a texture with no sender object to handle it, this shouldn't happen");
} }
} }
} }
@ -329,9 +340,9 @@ namespace OpenSim.Region.Environment.Modules
} }
catch (ArgumentOutOfRangeException) catch (ArgumentOutOfRangeException)
{ {
MainLog.Instance.Warn("TEXTURE", MainLog.Instance.Error("TEXTURE",
"Unable to separate texture into multiple packets: Array bounds failure on asset:" + "Unable to separate texture into multiple packets: Array bounds failure on asset:" +
m_asset.FullID.ToString() + "- TextureDownloadModule.cs. line:328"); m_asset.FullID.ToString() );
return; return;
} }
RequestUser.OutPacket(im, ThrottleOutPacketType.Texture); RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);