diff --git a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs index 6cffd706dd..b18672087a 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs @@ -60,14 +60,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP private sbyte m_discardLevel=-1; private uint m_packetNumber; private bool m_decoderequested = false; - private bool m_hasasset = false; + public bool m_hasasset = false; private bool m_asset_requested = false; private bool m_sentinfo = false; private uint m_stopPacket = 0; private const int cImagePacketSize = 1000; private const int cFirstPacketSize = 600; + private AssetBase m_asset = null; + private int m_assetDataLength = 0; + private LLImageManager m_image; + public J2KImage(LLImageManager image) { m_image = image; @@ -99,7 +103,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP return 0; try { - return (ushort)(((m_asset.Data.Length - cFirstPacketSize + cImagePacketSize - 1) / cImagePacketSize) + 1); + return (ushort)(((m_assetDataLength - cFirstPacketSize + cImagePacketSize - 1) / cImagePacketSize) + 1); } catch (Exception) { @@ -110,6 +114,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + public void DropAsset() + { + m_log.WarnFormat("[LLIMAGE MANAGER]: Dropping texture asset {0}", m_requestedUUID); + m_asset = null; + m_hasasset = false; + m_asset_requested = false; + } + public void J2KDecodedCallback(UUID AssetId, OpenJPEG.J2KLayerInfo[] layers) { m_image.m_outstandingtextures++; @@ -127,8 +139,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else { - m_asset = asset; + m_asset = asset; } + + m_assetDataLength = m_asset.Data.Length; + RunUpdate(); } @@ -150,8 +165,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP public int LastPacketSize() { if (m_packetNumber == 1) - return m_asset.Data.Length; - int lastsize = (m_asset.Data.Length - cFirstPacketSize) % cImagePacketSize; + return m_assetDataLength; + int lastsize = (m_assetDataLength - cFirstPacketSize) % cImagePacketSize; //If the last packet size is zero, it's really cImagePacketSize, it sits on the boundary if (lastsize == 0) { @@ -185,10 +200,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } // Do we have less then 1 packet's worth of data? - else if (m_asset.Data.Length <= cFirstPacketSize) + else if (m_assetDataLength <= cFirstPacketSize) { // Send only 1 packet - client.SendImageFirstPart(1, m_requestedUUID, (uint)m_asset.Data.Length, m_asset.Data, 2); + client.SendImageFirstPart(1, m_requestedUUID, (uint)m_assetDataLength, m_asset.Data, 2); m_stopPacket = 0; return true; } @@ -198,7 +213,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP try { Buffer.BlockCopy(m_asset.Data, 0, firstImageData, 0, (int)cFirstPacketSize); - client.SendImageFirstPart(TexturePacketCount(), m_requestedUUID, (uint)m_asset.Data.Length, firstImageData, 2); + client.SendImageFirstPart(TexturePacketCount(), m_requestedUUID, (uint)m_assetDataLength, firstImageData, 2); } catch (Exception) { @@ -216,13 +231,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP try { - if ((CurrentBytePosition() + cImagePacketSize) > m_asset.Data.Length) + if ((CurrentBytePosition() + cImagePacketSize) > m_assetDataLength) { imagePacketSize = LastPacketSize(); complete=true; - if ((CurrentBytePosition() + imagePacketSize) > m_asset.Data.Length) + if ((CurrentBytePosition() + imagePacketSize) > m_assetDataLength) { - imagePacketSize = m_asset.Data.Length - CurrentBytePosition(); + imagePacketSize = m_assetDataLength - CurrentBytePosition(); complete = true; } } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs index 295a5e6f99..b039049ad6 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs @@ -257,6 +257,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP J2KImage imagereq = m_imagestore[m_priorities.Values[x]]; if (imagereq.m_decoded == true && !imagereq.m_completedSendAtCurrentDiscardLevel) { + // we need to test this here now that we are dropping assets + if (!imagereq.m_hasasset) + { + m_log.WarnFormat("[LLIMAGE MANAGER]: Re-requesting the image asset {0}", imagereq.m_requestedUUID); + imagereq.RunUpdate(); + continue; + } + numCollected++; //SendPackets will send up to ten packets per cycle if (imagereq.SendPackets(m_client, maxpack)) @@ -264,8 +272,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP //Send complete if (!imagereq.m_completedSendAtCurrentDiscardLevel) { - imagereq.m_completedSendAtCurrentDiscardLevel = true; + // I think this field imagereq.m_completedSendAtCurrentDiscardLevel + // is completely redundant + //imagereq.m_completedSendAtCurrentDiscardLevel = true; + Interlocked.Decrement(ref m_outstandingtextures); + + // First and foremost, drop the reference to the asset + // so that the asset doesn't stay in memory forever. + // We'll Get it again from the asset service (usually cache) + // if/when the client requests it again. + // In order not to mess much with the current implementation + // of this management code, we drop only the asset reference + // but keep the image request itself. + imagereq.DropAsset(); + //Re-assign priority to bottom //Remove the old priority m_priorities.Remove(imagereq.m_designatedPriorityKey);