From 381f74276b94f9f635b08c4bccf3040fce5d59fb Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 19 Jan 2012 21:14:09 +0000 Subject: Add LLImageManager regression test for discard case --- .../Linden/UDP/Tests/LLImageManagerTests.cs | 53 ++++++++++++++++++++++ 1 file changed, 53 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs index bdc9c7d..118333c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs @@ -88,5 +88,58 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(1)); } + + [Test] + public void TestRequestAndDiscardImage() + { + TestHelpers.InMethod(); +// XmlConfigurator.Configure(); + + UUID imageId = TestHelpers.ParseTail(0x1); + string creatorId = TestHelpers.ParseTail(0x2).ToString(); + UUID userId = TestHelpers.ParseTail(0x3); + + J2KDecoderModule j2kdm = new J2KDecoderModule(); + + Scene scene = SceneHelpers.SetupScene(); + SceneHelpers.SetupSceneModules(scene, j2kdm); + + TestClient tc = new TestClient(SceneHelpers.GenerateAgentData(userId), scene); + LLImageManager llim = new LLImageManager(tc, scene.AssetService, j2kdm); + + using ( + Stream resource + = GetType().Assembly.GetManifestResourceStream( + "OpenSim.Region.ClientStack.LindenUDP.Tests.Resources.4-tile2.jp2")) + { + using (BinaryReader br = new BinaryReader(resource)) + { + AssetBase asset = new AssetBase(imageId, "Test Image", (sbyte)AssetType.Texture, creatorId); + asset.Data = br.ReadBytes(99999999); + scene.AssetService.Store(asset); + } + } + + TextureRequestArgs args = new TextureRequestArgs(); + args.RequestedAssetID = imageId; + args.DiscardLevel = 0; + args.PacketNumber = 1; + args.Priority = 5; + args.requestSequence = 1; + llim.EnqueueReq(args); + + // Now create a discard request + TextureRequestArgs discardArgs = new TextureRequestArgs(); + discardArgs.RequestedAssetID = imageId; + discardArgs.DiscardLevel = -1; + discardArgs.PacketNumber = 1; + discardArgs.Priority = 0; + discardArgs.requestSequence = 2; + llim.EnqueueReq(discardArgs); + + llim.ProcessImageQueue(20); + + Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(0)); + } } } \ No newline at end of file -- cgit v1.1 From 503faaea62502e1e86fc11bee1a322e060836f62 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 19 Jan 2012 21:23:40 +0000 Subject: refactor: separate out common parts of LLImageManagerTests --- .../Linden/UDP/Tests/LLImageManagerTests.cs | 88 ++++++++++------------ 1 file changed, 40 insertions(+), 48 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs index 118333c..f176964 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs @@ -45,24 +45,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests [TestFixture] public class LLImageManagerTests { - [Test] - public void TestRequestAndSendImage() - { - TestHelpers.InMethod(); -// XmlConfigurator.Configure(); - - UUID imageId = TestHelpers.ParseTail(0x1); - string creatorId = TestHelpers.ParseTail(0x2).ToString(); - UUID userId = TestHelpers.ParseTail(0x3); - - J2KDecoderModule j2kdm = new J2KDecoderModule(); - - Scene scene = SceneHelpers.SetupScene(); - SceneHelpers.SetupSceneModules(scene, j2kdm); - - TestClient tc = new TestClient(SceneHelpers.GenerateAgentData(userId), scene); - LLImageManager llim = new LLImageManager(tc, scene.AssetService, j2kdm); + private AssetBase m_testImageAsset; + private LLImageManager llim; + private TestClient tc; + [TestFixtureSetUp] + public void FixtureInit() + { using ( Stream resource = GetType().Assembly.GetManifestResourceStream( @@ -70,14 +59,42 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests { using (BinaryReader br = new BinaryReader(resource)) { - AssetBase asset = new AssetBase(imageId, "Test Image", (sbyte)AssetType.Texture, creatorId); - asset.Data = br.ReadBytes(99999999); - scene.AssetService.Store(asset); + m_testImageAsset + = new AssetBase( + TestHelpers.ParseTail(0x1), + "Test Image", + (sbyte)AssetType.Texture, + TestHelpers.ParseTail(0x2).ToString()); + + m_testImageAsset.Data = br.ReadBytes(99999999); } } + } + + [SetUp] + public void SetUp() + { + UUID userId = TestHelpers.ParseTail(0x3); + + J2KDecoderModule j2kdm = new J2KDecoderModule(); + + Scene scene = SceneHelpers.SetupScene(); + SceneHelpers.SetupSceneModules(scene, j2kdm); + + scene.AssetService.Store(m_testImageAsset); + + tc = new TestClient(SceneHelpers.GenerateAgentData(userId), scene); + llim = new LLImageManager(tc, scene.AssetService, j2kdm); + } + + [Test] + public void TestRequestAndSendImage() + { + TestHelpers.InMethod(); +// XmlConfigurator.Configure(); TextureRequestArgs args = new TextureRequestArgs(); - args.RequestedAssetID = TestHelpers.ParseTail(0x1); + args.RequestedAssetID = m_testImageAsset.FullID; args.DiscardLevel = 0; args.PacketNumber = 1; args.Priority = 5; @@ -95,33 +112,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests TestHelpers.InMethod(); // XmlConfigurator.Configure(); - UUID imageId = TestHelpers.ParseTail(0x1); - string creatorId = TestHelpers.ParseTail(0x2).ToString(); - UUID userId = TestHelpers.ParseTail(0x3); - - J2KDecoderModule j2kdm = new J2KDecoderModule(); - - Scene scene = SceneHelpers.SetupScene(); - SceneHelpers.SetupSceneModules(scene, j2kdm); - - TestClient tc = new TestClient(SceneHelpers.GenerateAgentData(userId), scene); - LLImageManager llim = new LLImageManager(tc, scene.AssetService, j2kdm); - - using ( - Stream resource - = GetType().Assembly.GetManifestResourceStream( - "OpenSim.Region.ClientStack.LindenUDP.Tests.Resources.4-tile2.jp2")) - { - using (BinaryReader br = new BinaryReader(resource)) - { - AssetBase asset = new AssetBase(imageId, "Test Image", (sbyte)AssetType.Texture, creatorId); - asset.Data = br.ReadBytes(99999999); - scene.AssetService.Store(asset); - } - } - TextureRequestArgs args = new TextureRequestArgs(); - args.RequestedAssetID = imageId; + args.RequestedAssetID = m_testImageAsset.FullID; args.DiscardLevel = 0; args.PacketNumber = 1; args.Priority = 5; @@ -130,7 +122,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests // Now create a discard request TextureRequestArgs discardArgs = new TextureRequestArgs(); - discardArgs.RequestedAssetID = imageId; + discardArgs.RequestedAssetID = m_testImageAsset.FullID; discardArgs.DiscardLevel = -1; discardArgs.PacketNumber = 1; discardArgs.Priority = 0; -- cgit v1.1 From d38e2c0c91b684d54974865d3ac2fb88c3354c21 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 19 Jan 2012 21:57:12 +0000 Subject: Add image not in database test for LLImageManager --- OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs | 3 ++ .../ClientStack/Linden/UDP/LLImageManager.cs | 29 +++++++++++++------ .../Linden/UDP/Tests/LLImageManagerTests.cs | 33 ++++++++++++++++++---- 3 files changed, 52 insertions(+), 13 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs index bbd2c43..8dd76d8 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs @@ -377,6 +377,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP private void AssetReceived(string id, Object sender, AssetBase asset) { +// m_log.DebugFormat( +// "[J2KIMAGE]: Received asset {0} ({1} bytes)", id, asset != null ? asset.Data.Length.ToString() : "n/a"); + UUID assetID = UUID.Zero; if (asset != null) { diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs index 7bfb844..a48251f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs @@ -55,18 +55,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private bool m_shuttingdown; private AssetBase m_missingImage; - private IClientAPI m_client; //Client we're assigned to - private IAssetService m_assetCache; //Asset Cache - private IJ2KDecoder m_j2kDecodeModule; //Our J2K module + private IAssetService m_assetCache; + private IJ2KDecoder m_j2kDecodeModule; + + /// + /// Priority queue for determining which image to send first. + /// private C5.IntervalHeap m_priorityQueue = new C5.IntervalHeap(10, new J2KImageComparer()); + + /// + /// Used to control thread access to the priority queue. + /// private object m_syncRoot = new object(); - public IClientAPI Client { get { return m_client; } } + /// + /// Client served by this image manager + /// + public IClientAPI Client { get; private set; } + public AssetBase MissingImage { get { return m_missingImage; } } public LLImageManager(IClientAPI client, IAssetService pAssetCache, IJ2KDecoder pJ2kDecodeModule) { - m_client = client; + Client = client; m_assetCache = pAssetCache; if (pAssetCache != null) @@ -90,7 +101,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Do a linear search for this texture download lock (m_syncRoot) + { m_priorityQueue.Find(delegate(J2KImage img) { return img.TextureID == newRequest.RequestedAssetID; }, out imgrequest); + } if (imgrequest != null) { @@ -178,8 +191,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP imgrequest = new J2KImage(this); imgrequest.J2KDecoder = m_j2kDecodeModule; imgrequest.AssetService = m_assetCache; - imgrequest.AgentID = m_client.AgentId; - imgrequest.InventoryAccessModule = m_client.Scene.RequestModuleInterface(); + imgrequest.AgentID = Client.AgentId; + imgrequest.InventoryAccessModule = Client.Scene.RequestModuleInterface(); imgrequest.DiscardLevel = newRequest.DiscardLevel; imgrequest.StartPacket = Math.Max(1, newRequest.PacketNumber); imgrequest.Priority = newRequest.Priority; @@ -210,7 +223,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (image.IsDecoded) { int sent; - bool imageDone = image.SendPackets(m_client, packetsToSend - packetsSent, out sent); + bool imageDone = image.SendPackets(Client, packetsToSend - packetsSent, out sent); packetsSent += sent; // If the send is complete, destroy any knowledge of this transfer diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs index f176964..1b68d68 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs @@ -46,6 +46,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests public class LLImageManagerTests { private AssetBase m_testImageAsset; + private Scene scene; private LLImageManager llim; private TestClient tc; @@ -78,21 +79,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests J2KDecoderModule j2kdm = new J2KDecoderModule(); - Scene scene = SceneHelpers.SetupScene(); + scene = SceneHelpers.SetupScene(); SceneHelpers.SetupSceneModules(scene, j2kdm); - scene.AssetService.Store(m_testImageAsset); - tc = new TestClient(SceneHelpers.GenerateAgentData(userId), scene); llim = new LLImageManager(tc, scene.AssetService, j2kdm); } [Test] - public void TestRequestAndSendImage() + public void TestSendImage() { TestHelpers.InMethod(); // XmlConfigurator.Configure(); + scene.AssetService.Store(m_testImageAsset); + TextureRequestArgs args = new TextureRequestArgs(); args.RequestedAssetID = m_testImageAsset.FullID; args.DiscardLevel = 0; @@ -107,11 +108,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests } [Test] - public void TestRequestAndDiscardImage() + public void TestDiscardImage() { TestHelpers.InMethod(); // XmlConfigurator.Configure(); + scene.AssetService.Store(m_testImageAsset); + TextureRequestArgs args = new TextureRequestArgs(); args.RequestedAssetID = m_testImageAsset.FullID; args.DiscardLevel = 0; @@ -133,5 +136,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(0)); } + + [Test] + public void TestMissingImage() + { + TestHelpers.InMethod(); +// XmlConfigurator.Configure(); + + TextureRequestArgs args = new TextureRequestArgs(); + args.RequestedAssetID = m_testImageAsset.FullID; + args.DiscardLevel = 0; + args.PacketNumber = 1; + args.Priority = 5; + args.requestSequence = 1; + + llim.EnqueueReq(args); + llim.ProcessImageQueue(20); + + Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(0)); + Assert.That(tc.SentImageNotInDatabasePackets.Count, Is.EqualTo(1)); + } } } \ No newline at end of file -- cgit v1.1 From ea72428c9d3fa27ab43bb3e0b2e297bf3b22861e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 19 Jan 2012 23:09:16 +0000 Subject: Allow a viewer UDP image request retry to trigger another asset fetch if an existing fetch hasn't responded before a timeout. This is to stop a high priority image/texture request from blocking the entire download queue if its asset fetch got dropped for some reason. --- OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs | 32 ++++++++++++++++++++-- .../ClientStack/Linden/UDP/LLImageManager.cs | 6 ++-- 2 files changed, 32 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs index 8dd76d8..afbe56b 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs @@ -45,6 +45,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP private const int IMAGE_PACKET_SIZE = 1000; private const int FIRST_PACKET_SIZE = 600; + /// + /// If we've requested an asset but not received it in this ticks timeframe, then allow a duplicate + /// request from the client to trigger a fresh asset request. + /// + /// + /// There are 10,000 ticks in a millisecond + /// + private const int ASSET_REQUEST_TIMEOUT = 100000000; + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); public uint LastSequence; @@ -57,8 +66,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP public UUID AgentID; public IInventoryAccessModule InventoryAccessModule; private OpenJPEG.J2KLayerInfo[] m_layers; + + /// + /// Has this request decoded the asset data? + /// public bool IsDecoded { get; private set; } + + /// + /// Has this request received the required asset data? + /// public bool HasAsset { get; private set; } + + /// + /// Time in milliseconds at which the asset was requested. + /// + public long AssetRequestTime { get; private set; } + public C5.IPriorityQueueHandle PriorityQueueHandle; private uint m_currentPacket; @@ -123,10 +146,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if (!HasAsset) { - if (!m_assetRequested) + if (!m_assetRequested || DateTime.UtcNow.Ticks > AssetRequestTime + ASSET_REQUEST_TIMEOUT) { +// m_log.DebugFormat( +// "[J2KIMAGE]: Requesting asset {0} from request in packet {1}, already requested? {2}, due to timeout? {3}", +// TextureID, LastSequence, m_assetRequested, DateTime.UtcNow.Ticks > AssetRequestTime + ASSET_REQUEST_TIMEOUT); + m_assetRequested = true; -// m_log.DebugFormat("[J2KIMAGE]: Requesting asset {0}", TextureID); + AssetRequestTime = DateTime.UtcNow.Ticks; + AssetService.Get(TextureID.ToString(), this, AssetReceived); } } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs index a48251f..073c357 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs @@ -101,9 +101,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Do a linear search for this texture download lock (m_syncRoot) - { m_priorityQueue.Find(delegate(J2KImage img) { return img.TextureID == newRequest.RequestedAssetID; }, out imgrequest); - } if (imgrequest != null) { @@ -124,8 +122,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP // "[LL IMAGE MANAGER]: Received duplicate of existing request for {0}, start packet {1} from {2}", // newRequest.RequestedAssetID, newRequest.PacketNumber, m_client.Name); - //m_log.DebugFormat("[TEX]: (UPD) ID={0}: D={1}, S={2}, P={3}", - // newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority); +// m_log.DebugFormat("[TEX]: (UPD) ID={0}: D={1}, S={2}, P={3}", +// newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority); //Check the packet sequence to make sure this isn't older than //one we've already received -- cgit v1.1