diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP')
3 files changed, 143 insertions, 33 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs index bbd2c43..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 | |||
45 | private const int IMAGE_PACKET_SIZE = 1000; | 45 | private const int IMAGE_PACKET_SIZE = 1000; |
46 | private const int FIRST_PACKET_SIZE = 600; | 46 | private const int FIRST_PACKET_SIZE = 600; |
47 | 47 | ||
48 | /// <summary> | ||
49 | /// If we've requested an asset but not received it in this ticks timeframe, then allow a duplicate | ||
50 | /// request from the client to trigger a fresh asset request. | ||
51 | /// </summary> | ||
52 | /// <remarks> | ||
53 | /// There are 10,000 ticks in a millisecond | ||
54 | /// </remarks> | ||
55 | private const int ASSET_REQUEST_TIMEOUT = 100000000; | ||
56 | |||
48 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 57 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
49 | 58 | ||
50 | public uint LastSequence; | 59 | public uint LastSequence; |
@@ -57,8 +66,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
57 | public UUID AgentID; | 66 | public UUID AgentID; |
58 | public IInventoryAccessModule InventoryAccessModule; | 67 | public IInventoryAccessModule InventoryAccessModule; |
59 | private OpenJPEG.J2KLayerInfo[] m_layers; | 68 | private OpenJPEG.J2KLayerInfo[] m_layers; |
69 | |||
70 | /// <summary> | ||
71 | /// Has this request decoded the asset data? | ||
72 | /// </summary> | ||
60 | public bool IsDecoded { get; private set; } | 73 | public bool IsDecoded { get; private set; } |
74 | |||
75 | /// <summary> | ||
76 | /// Has this request received the required asset data? | ||
77 | /// </summary> | ||
61 | public bool HasAsset { get; private set; } | 78 | public bool HasAsset { get; private set; } |
79 | |||
80 | /// <summary> | ||
81 | /// Time in milliseconds at which the asset was requested. | ||
82 | /// </summary> | ||
83 | public long AssetRequestTime { get; private set; } | ||
84 | |||
62 | public C5.IPriorityQueueHandle<J2KImage> PriorityQueueHandle; | 85 | public C5.IPriorityQueueHandle<J2KImage> PriorityQueueHandle; |
63 | 86 | ||
64 | private uint m_currentPacket; | 87 | private uint m_currentPacket; |
@@ -123,10 +146,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
123 | { | 146 | { |
124 | if (!HasAsset) | 147 | if (!HasAsset) |
125 | { | 148 | { |
126 | if (!m_assetRequested) | 149 | if (!m_assetRequested || DateTime.UtcNow.Ticks > AssetRequestTime + ASSET_REQUEST_TIMEOUT) |
127 | { | 150 | { |
151 | // m_log.DebugFormat( | ||
152 | // "[J2KIMAGE]: Requesting asset {0} from request in packet {1}, already requested? {2}, due to timeout? {3}", | ||
153 | // TextureID, LastSequence, m_assetRequested, DateTime.UtcNow.Ticks > AssetRequestTime + ASSET_REQUEST_TIMEOUT); | ||
154 | |||
128 | m_assetRequested = true; | 155 | m_assetRequested = true; |
129 | // m_log.DebugFormat("[J2KIMAGE]: Requesting asset {0}", TextureID); | 156 | AssetRequestTime = DateTime.UtcNow.Ticks; |
157 | |||
130 | AssetService.Get(TextureID.ToString(), this, AssetReceived); | 158 | AssetService.Get(TextureID.ToString(), this, AssetReceived); |
131 | } | 159 | } |
132 | } | 160 | } |
@@ -377,6 +405,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
377 | 405 | ||
378 | private void AssetReceived(string id, Object sender, AssetBase asset) | 406 | private void AssetReceived(string id, Object sender, AssetBase asset) |
379 | { | 407 | { |
408 | // m_log.DebugFormat( | ||
409 | // "[J2KIMAGE]: Received asset {0} ({1} bytes)", id, asset != null ? asset.Data.Length.ToString() : "n/a"); | ||
410 | |||
380 | UUID assetID = UUID.Zero; | 411 | UUID assetID = UUID.Zero; |
381 | if (asset != null) | 412 | if (asset != null) |
382 | { | 413 | { |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs index 7bfb844..073c357 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 | |||
55 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 55 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
56 | private bool m_shuttingdown; | 56 | private bool m_shuttingdown; |
57 | private AssetBase m_missingImage; | 57 | private AssetBase m_missingImage; |
58 | private IClientAPI m_client; //Client we're assigned to | 58 | private IAssetService m_assetCache; |
59 | private IAssetService m_assetCache; //Asset Cache | 59 | private IJ2KDecoder m_j2kDecodeModule; |
60 | private IJ2KDecoder m_j2kDecodeModule; //Our J2K module | 60 | |
61 | /// <summary> | ||
62 | /// Priority queue for determining which image to send first. | ||
63 | /// </summary> | ||
61 | private C5.IntervalHeap<J2KImage> m_priorityQueue = new C5.IntervalHeap<J2KImage>(10, new J2KImageComparer()); | 64 | private C5.IntervalHeap<J2KImage> m_priorityQueue = new C5.IntervalHeap<J2KImage>(10, new J2KImageComparer()); |
65 | |||
66 | /// <summary> | ||
67 | /// Used to control thread access to the priority queue. | ||
68 | /// </summary> | ||
62 | private object m_syncRoot = new object(); | 69 | private object m_syncRoot = new object(); |
63 | 70 | ||
64 | public IClientAPI Client { get { return m_client; } } | 71 | /// <summary> |
72 | /// Client served by this image manager | ||
73 | /// </summary> | ||
74 | public IClientAPI Client { get; private set; } | ||
75 | |||
65 | public AssetBase MissingImage { get { return m_missingImage; } } | 76 | public AssetBase MissingImage { get { return m_missingImage; } } |
66 | 77 | ||
67 | public LLImageManager(IClientAPI client, IAssetService pAssetCache, IJ2KDecoder pJ2kDecodeModule) | 78 | public LLImageManager(IClientAPI client, IAssetService pAssetCache, IJ2KDecoder pJ2kDecodeModule) |
68 | { | 79 | { |
69 | m_client = client; | 80 | Client = client; |
70 | m_assetCache = pAssetCache; | 81 | m_assetCache = pAssetCache; |
71 | 82 | ||
72 | if (pAssetCache != null) | 83 | if (pAssetCache != null) |
@@ -111,8 +122,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
111 | // "[LL IMAGE MANAGER]: Received duplicate of existing request for {0}, start packet {1} from {2}", | 122 | // "[LL IMAGE MANAGER]: Received duplicate of existing request for {0}, start packet {1} from {2}", |
112 | // newRequest.RequestedAssetID, newRequest.PacketNumber, m_client.Name); | 123 | // newRequest.RequestedAssetID, newRequest.PacketNumber, m_client.Name); |
113 | 124 | ||
114 | //m_log.DebugFormat("[TEX]: (UPD) ID={0}: D={1}, S={2}, P={3}", | 125 | // m_log.DebugFormat("[TEX]: (UPD) ID={0}: D={1}, S={2}, P={3}", |
115 | // newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority); | 126 | // newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority); |
116 | 127 | ||
117 | //Check the packet sequence to make sure this isn't older than | 128 | //Check the packet sequence to make sure this isn't older than |
118 | //one we've already received | 129 | //one we've already received |
@@ -178,8 +189,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
178 | imgrequest = new J2KImage(this); | 189 | imgrequest = new J2KImage(this); |
179 | imgrequest.J2KDecoder = m_j2kDecodeModule; | 190 | imgrequest.J2KDecoder = m_j2kDecodeModule; |
180 | imgrequest.AssetService = m_assetCache; | 191 | imgrequest.AssetService = m_assetCache; |
181 | imgrequest.AgentID = m_client.AgentId; | 192 | imgrequest.AgentID = Client.AgentId; |
182 | imgrequest.InventoryAccessModule = m_client.Scene.RequestModuleInterface<IInventoryAccessModule>(); | 193 | imgrequest.InventoryAccessModule = Client.Scene.RequestModuleInterface<IInventoryAccessModule>(); |
183 | imgrequest.DiscardLevel = newRequest.DiscardLevel; | 194 | imgrequest.DiscardLevel = newRequest.DiscardLevel; |
184 | imgrequest.StartPacket = Math.Max(1, newRequest.PacketNumber); | 195 | imgrequest.StartPacket = Math.Max(1, newRequest.PacketNumber); |
185 | imgrequest.Priority = newRequest.Priority; | 196 | imgrequest.Priority = newRequest.Priority; |
@@ -210,7 +221,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
210 | if (image.IsDecoded) | 221 | if (image.IsDecoded) |
211 | { | 222 | { |
212 | int sent; | 223 | int sent; |
213 | bool imageDone = image.SendPackets(m_client, packetsToSend - packetsSent, out sent); | 224 | bool imageDone = image.SendPackets(Client, packetsToSend - packetsSent, out sent); |
214 | packetsSent += sent; | 225 | packetsSent += sent; |
215 | 226 | ||
216 | // If the send is complete, destroy any knowledge of this transfer | 227 | // 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 bdc9c7d..1b68d68 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs | |||
@@ -45,24 +45,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
45 | [TestFixture] | 45 | [TestFixture] |
46 | public class LLImageManagerTests | 46 | public class LLImageManagerTests |
47 | { | 47 | { |
48 | [Test] | 48 | private AssetBase m_testImageAsset; |
49 | public void TestRequestAndSendImage() | 49 | private Scene scene; |
50 | { | 50 | private LLImageManager llim; |
51 | TestHelpers.InMethod(); | 51 | private TestClient tc; |
52 | // XmlConfigurator.Configure(); | ||
53 | |||
54 | UUID imageId = TestHelpers.ParseTail(0x1); | ||
55 | string creatorId = TestHelpers.ParseTail(0x2).ToString(); | ||
56 | UUID userId = TestHelpers.ParseTail(0x3); | ||
57 | |||
58 | J2KDecoderModule j2kdm = new J2KDecoderModule(); | ||
59 | |||
60 | Scene scene = SceneHelpers.SetupScene(); | ||
61 | SceneHelpers.SetupSceneModules(scene, j2kdm); | ||
62 | |||
63 | TestClient tc = new TestClient(SceneHelpers.GenerateAgentData(userId), scene); | ||
64 | LLImageManager llim = new LLImageManager(tc, scene.AssetService, j2kdm); | ||
65 | 52 | ||
53 | [TestFixtureSetUp] | ||
54 | public void FixtureInit() | ||
55 | { | ||
66 | using ( | 56 | using ( |
67 | Stream resource | 57 | Stream resource |
68 | = GetType().Assembly.GetManifestResourceStream( | 58 | = GetType().Assembly.GetManifestResourceStream( |
@@ -70,14 +60,42 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
70 | { | 60 | { |
71 | using (BinaryReader br = new BinaryReader(resource)) | 61 | using (BinaryReader br = new BinaryReader(resource)) |
72 | { | 62 | { |
73 | AssetBase asset = new AssetBase(imageId, "Test Image", (sbyte)AssetType.Texture, creatorId); | 63 | m_testImageAsset |
74 | asset.Data = br.ReadBytes(99999999); | 64 | = new AssetBase( |
75 | scene.AssetService.Store(asset); | 65 | TestHelpers.ParseTail(0x1), |
66 | "Test Image", | ||
67 | (sbyte)AssetType.Texture, | ||
68 | TestHelpers.ParseTail(0x2).ToString()); | ||
69 | |||
70 | m_testImageAsset.Data = br.ReadBytes(99999999); | ||
76 | } | 71 | } |
77 | } | 72 | } |
73 | } | ||
74 | |||
75 | [SetUp] | ||
76 | public void SetUp() | ||
77 | { | ||
78 | UUID userId = TestHelpers.ParseTail(0x3); | ||
79 | |||
80 | J2KDecoderModule j2kdm = new J2KDecoderModule(); | ||
81 | |||
82 | scene = SceneHelpers.SetupScene(); | ||
83 | SceneHelpers.SetupSceneModules(scene, j2kdm); | ||
84 | |||
85 | tc = new TestClient(SceneHelpers.GenerateAgentData(userId), scene); | ||
86 | llim = new LLImageManager(tc, scene.AssetService, j2kdm); | ||
87 | } | ||
88 | |||
89 | [Test] | ||
90 | public void TestSendImage() | ||
91 | { | ||
92 | TestHelpers.InMethod(); | ||
93 | // XmlConfigurator.Configure(); | ||
94 | |||
95 | scene.AssetService.Store(m_testImageAsset); | ||
78 | 96 | ||
79 | TextureRequestArgs args = new TextureRequestArgs(); | 97 | TextureRequestArgs args = new TextureRequestArgs(); |
80 | args.RequestedAssetID = TestHelpers.ParseTail(0x1); | 98 | args.RequestedAssetID = m_testImageAsset.FullID; |
81 | args.DiscardLevel = 0; | 99 | args.DiscardLevel = 0; |
82 | args.PacketNumber = 1; | 100 | args.PacketNumber = 1; |
83 | args.Priority = 5; | 101 | args.Priority = 5; |
@@ -88,5 +106,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
88 | 106 | ||
89 | Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(1)); | 107 | Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(1)); |
90 | } | 108 | } |
109 | |||
110 | [Test] | ||
111 | public void TestDiscardImage() | ||
112 | { | ||
113 | TestHelpers.InMethod(); | ||
114 | // XmlConfigurator.Configure(); | ||
115 | |||
116 | scene.AssetService.Store(m_testImageAsset); | ||
117 | |||
118 | TextureRequestArgs args = new TextureRequestArgs(); | ||
119 | args.RequestedAssetID = m_testImageAsset.FullID; | ||
120 | args.DiscardLevel = 0; | ||
121 | args.PacketNumber = 1; | ||
122 | args.Priority = 5; | ||
123 | args.requestSequence = 1; | ||
124 | llim.EnqueueReq(args); | ||
125 | |||
126 | // Now create a discard request | ||
127 | TextureRequestArgs discardArgs = new TextureRequestArgs(); | ||
128 | discardArgs.RequestedAssetID = m_testImageAsset.FullID; | ||
129 | discardArgs.DiscardLevel = -1; | ||
130 | discardArgs.PacketNumber = 1; | ||
131 | discardArgs.Priority = 0; | ||
132 | discardArgs.requestSequence = 2; | ||
133 | llim.EnqueueReq(discardArgs); | ||
134 | |||
135 | llim.ProcessImageQueue(20); | ||
136 | |||
137 | Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(0)); | ||
138 | } | ||
139 | |||
140 | [Test] | ||
141 | public void TestMissingImage() | ||
142 | { | ||
143 | TestHelpers.InMethod(); | ||
144 | // XmlConfigurator.Configure(); | ||
145 | |||
146 | TextureRequestArgs args = new TextureRequestArgs(); | ||
147 | args.RequestedAssetID = m_testImageAsset.FullID; | ||
148 | args.DiscardLevel = 0; | ||
149 | args.PacketNumber = 1; | ||
150 | args.Priority = 5; | ||
151 | args.requestSequence = 1; | ||
152 | |||
153 | llim.EnqueueReq(args); | ||
154 | llim.ProcessImageQueue(20); | ||
155 | |||
156 | Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(0)); | ||
157 | Assert.That(tc.SentImageNotInDatabasePackets.Count, Is.EqualTo(1)); | ||
158 | } | ||
91 | } | 159 | } |
92 | } \ No newline at end of file | 160 | } \ No newline at end of file |