void AddImageToQueue(J2KImage image) { image.PriorityQueueHandle = null; lock (m_syncRoot) try { m_priorityQueue.Add(ref image.PriorityQueueHandle, image); } catch (Exception) { } }
private void AddImageToQueue(J2KImage image) { lock (m_syncRoot) try { m_queue.Enqueue(image, image.Priority); } catch (Exception) { } }
private void RemoveImageFromQueue(J2KImage image) { lock (m_syncRoot) { try { m_priorityQueue.Delete(image.PriorityQueueHandle); } catch (Exception) { } } }
void UpdateImageInQueue(J2KImage image) { lock (m_syncRoot) { try { m_priorityQueue.Replace(image.PriorityQueueHandle, image); } catch (Exception) { image.PriorityQueueHandle = null; m_priorityQueue.Add(ref image.PriorityQueueHandle, image); } } }
J2KImage GetHighestPriorityImage() { J2KImage image = null; lock (m_syncRoot) { if (m_priorityQueue.Count > 0) { try { image = m_priorityQueue.FindMax(); } catch (Exception) { } } } return(image); }
public bool ProcessImageQueue(int packetsToSend) { int StartTime = Util.EnvironmentTickCount(); int packetsSent = 0; while (packetsSent < packetsToSend) { J2KImage image = GetHighestPriorityImage(); // If null was returned, the texture priority queue is currently empty if (image == null) { return(false); } if (image.IsDecoded) { int sent; bool imageDone = image.SendPackets(m_client, packetsToSend - packetsSent, out sent); packetsSent += sent; // If the send is complete, destroy any knowledge of this transfer if (imageDone) { RemoveImageFromQueue(image); } } else { // TODO: This is a limitation of how LLImageManager is currently // written. Undecoded textures should not be going into the priority // queue, because a high priority undecoded texture will clog up the // pipeline for a client return(true); } } int EndTime = Util.EnvironmentTickCountSubtract(StartTime); IMonitorModule module = m_client.Scene.RequestModuleInterface <IMonitorModule>(); if (module != null) { IImageFrameTimeMonitor monitor = (IImageFrameTimeMonitor)module.GetMonitor(m_client.Scene.RegionInfo.RegionID.ToString(), "Images Frame Time"); monitor.AddImageTime(EndTime); } return(m_priorityQueue.Count > 0); }
public bool ProcessImageQueue(int packetsToSend) { int packetsSent = 0; while (packetsSent < packetsToSend) { J2KImage image = GetHighestPriorityImage(); // If null was returned, the texture priority queue is currently empty if (image == null) { break; } if (image.IsDecoded) { int sent; bool imageDone = image.SendPackets(Client, packetsToSend - packetsSent, out sent); packetsSent += sent; // If the send is complete, destroy any knowledge of this transfer if (imageDone) { RemoveImageFromQueue(image); } } else { // TODO: This is a limitation of how LLImageManager is currently // written. Undecoded textures should not be going into the priority // queue, because a high priority undecoded texture will clog up the // pipeline for a client // m_log.DebugFormat( // "[LL IMAGE MANAGER]: Exiting image queue processing early on encountering undecoded image {0}", // image.TextureID); break; } } // if (packetsSent != 0) // m_log.DebugFormat("[LL IMAGE MANAGER]: Processed {0} packets from image queue", packetsSent); return(m_priorityQueue.Count > 0); }
private J2KImage GetHighestPriorityImage() { J2KImage image = null; lock (m_syncRoot) { if (m_queue.Count > 0) { try { image = m_queue.Dequeue().Value; } catch (Exception) { } } } return(image); }
public bool ProcessImageQueue(int packetsToSend) { int packetsSent = 0; while (packetsSent < packetsToSend) { J2KImage image = GetHighestPriorityImage(); // If null was returned, the texture priority queue is currently empty if (image == null) { return(false); } image.CheckDoFirstUpdate(); if (image.IsDecoded) { int sent; bool imageDone = image.SendPackets(m_client, packetsToSend - packetsSent, out sent); packetsSent += sent; // If the send is complete, destroy any knowledge of this transfer if (imageDone) { RemoveImageFromQueue(image); } } else { // TODO: This is a limitation of how LLImageManager is currently // written. Undecoded textures should not be going into the priority // queue, because a high priority undecoded texture will clog up the // pipeline for a client return(true); } } return(m_priorityQueue.Count > 0); }
private J2KImage GetHighestPriorityImage() { J2KImage image = null; lock (m_syncRoot) { if (m_queue.Count > 0) { try { PriorityQueueItem <J2KImage, float> item; if (m_queue.TryDequeue(out item)) { image = item.Value; } } catch (Exception) { } } } return(image); }
public bool HasUpdates() { J2KImage image = GetHighestPriorityImage(); return(image != null && image.IsDecoded); }
public bool ProcessImageQueue(int packetsToSend) { int StartTime = Util.EnvironmentTickCount(); int packetsSent = 0; List <J2KImage> imagesToReAdd = new List <J2KImage>(); while (packetsSent < packetsToSend) { J2KImage image = GetHighestPriorityImage(); // If null was returned, the texture priority queue is currently empty if (image == null) { break; //Break so that we add any images back that we might remove because they arn't finished decoding } if (image.IsDecoded) { if (image.Layers == null) { //We don't have it, tell the client that it doesn't exist m_client.SendAssetUploadCompleteMessage((sbyte)AssetType.Texture, false, image.TextureID); RemoveImageFromQueue(image); packetsSent++; } else { int sent; bool imageDone = image.SendPackets(m_client, packetsToSend - packetsSent, out sent); packetsSent += sent; // If the send is complete, destroy any knowledge of this transfer if (imageDone) { RemoveImageFromQueue(image); } } } else { //Add it to the other queue and delete it from the top imagesToReAdd.Add(image); m_priorityQueue.DeleteMax(); packetsSent++; //We tried to send one // UNTODO: This was a limitation of how LLImageManager is currently // written. Undecoded textures should not be going into the priority // queue, because a high priority undecoded texture will clog up the // pipeline for a client //return true; } } //Add all the ones we removed so that we wouldn't block the queue if (imagesToReAdd.Count != 0) { foreach (J2KImage image in imagesToReAdd) { this.AddImageToQueue(image); } } int EndTime = Util.EnvironmentTickCountSubtract(StartTime); IMonitorModule module = m_client.Scene.RequestModuleInterface <IMonitorModule>(); if (module != null) { IImageFrameTimeMonitor monitor = (IImageFrameTimeMonitor)module.GetMonitor(m_client.Scene.RegionInfo.RegionID.ToString(), "Images Frame Time"); monitor.AddImageTime(EndTime); } return(m_priorityQueue.Count > 0); }
public void ProcessImageQueue(int count) { // this can happen during Close() if (m_client == null) { return; } //Count is the number of textures we want to process in one go. //As part of this class re-write, that number will probably rise //since we're processing in a more efficient manner. int numCollected = 0; //Calculate our threshold int threshold; if (m_lastloopprocessed == 0) { if (m_client.PacketHandler == null || m_client.PacketHandler.PacketQueue == null || m_client.PacketHandler.PacketQueue.TextureThrottle == null) { return; } //This is decent for a semi fast machine, but we'll calculate it more accurately based on time below threshold = m_client.PacketHandler.PacketQueue.TextureThrottle.Current / 6300; m_lastloopprocessed = DateTime.Now.Ticks; } else { double throttleseconds = ((double)DateTime.Now.Ticks - (double)m_lastloopprocessed) / (double)TimeSpan.TicksPerSecond; throttleseconds = throttleseconds * m_client.PacketHandler.PacketQueue.TextureThrottle.Current; //Average of 1000 bytes per packet throttleseconds = throttleseconds / 1000; //Safe-zone multiplier of 2.0 threshold = (int)(throttleseconds * 2.0); m_lastloopprocessed = DateTime.Now.Ticks; } if (threshold < 10) { threshold = 10; } if (m_client.PacketHandler == null) { return; } if (m_client.PacketHandler.PacketQueue == null) { return; } //First of all make sure our packet queue isn't above our threshold //Uncomment this to see what the texture stack is doing //m_log.Debug("Queue: " + m_client.PacketHandler.PacketQueue.TextureOutgoingPacketQueueCount.ToString() + " Threshold: " + threshold.ToString() + " outstanding: " + m_outstandingtextures.ToString()); if (m_client.PacketHandler.PacketQueue.TextureOutgoingPacketQueueCount < threshold && m_outstandingtextures > 0) { bool justreset = false; for (int x = m_priorities.Count - 1; x > -1; x--) { J2KImage imagereq = m_imagestore[m_priorities.Values[x]]; if (imagereq.m_decoded == true && !imagereq.m_completedSendAtCurrentDiscardLevel) { numCollected++; //SendPackets will send up to ten packets per cycle if (imagereq.SendPackets(m_client)) { //Send complete if (!imagereq.m_completedSendAtCurrentDiscardLevel) { imagereq.m_completedSendAtCurrentDiscardLevel = true; m_outstandingtextures--; //Re-assign priority to bottom //Remove the old priority m_priorities.Remove(imagereq.m_designatedPriorityKey); int lowest; if (m_priorities.Count > 0) { lowest = (int)m_priorities.Keys[0]; lowest--; } else { lowest = -10000; } m_priorities.Add((double)lowest, imagereq.m_requestedUUID); imagereq.m_designatedPriorityKey = (double)lowest; if (m_priorityresolver.ContainsKey((int)lowest)) { m_priorityresolver[(int)lowest]++; } else { m_priorityresolver.Add((int)lowest, 0); } } } if (numCollected == count) { break; } } if (numCollected == count || m_outstandingtextures == 0) { break; } if (numCollected % m_outstandingtextures == 0 && !justreset) { //We've gotten as much as we can from the stack, //reset to the top so that we can send MOAR DATA (nomnomnom)! x = m_priorities.Count - 1; justreset = true; //prevents us from getting stuck in a loop } } } }
public void EnqueueReq(TextureRequestArgs newRequest) { //newRequest is the properties of our new texture fetch request. //Basically, here is where we queue up "new" requests.. // .. or modify existing requests to suit. //Make sure we're not shutting down.. if (!m_shuttingdown) { //Do we already know about this UUID? if (m_imagestore.ContainsKey(newRequest.RequestedAssetID)) { //Check the packet sequence to make sure this isn't older than //one we've already received J2KImage imgrequest = m_imagestore[newRequest.RequestedAssetID]; // This is the inbound request sequence number. We can ignore // "old" ones. if (newRequest.requestSequence > imgrequest.m_lastSequence) { imgrequest.m_lastSequence = newRequest.requestSequence; //Check the priority double priority = imgrequest.m_requestedPriority; if (priority != newRequest.Priority) { //Remove the old priority m_priorities.Remove(imgrequest.m_designatedPriorityKey); //Assign a new unique priority imgrequest.m_requestedPriority = newRequest.Priority; imgrequest.m_designatedPriorityKey = AssignPriority(newRequest.RequestedAssetID, newRequest.Priority); } //Update the requested discard level imgrequest.m_requestedDiscardLevel = newRequest.DiscardLevel; //Update the requested packet number imgrequest.m_requestedPacketNumber = newRequest.PacketNumber; //Check if this will create an outstanding texture request bool activated = imgrequest.m_completedSendAtCurrentDiscardLevel; //Run an update imgrequest.RunUpdate(); if (activated && !imgrequest.m_completedSendAtCurrentDiscardLevel && imgrequest.m_decoded) { Interlocked.Increment(ref m_outstandingtextures); } } } else { J2KImage imgrequest = new J2KImage(this); //Assign our missing substitute imgrequest.m_MissingSubstitute = m_missingsubstitute; //Assign our decoder module imgrequest.m_j2kDecodeModule = m_j2kDecodeModule; //Assign our asset cache module imgrequest.m_assetCache = m_assetCache; //Assign a priority based on our request imgrequest.m_designatedPriorityKey = AssignPriority(newRequest.RequestedAssetID, newRequest.Priority); //Assign the requested discard level imgrequest.m_requestedDiscardLevel = newRequest.DiscardLevel; //Assign the requested packet number imgrequest.m_requestedPacketNumber = newRequest.PacketNumber; //Assign the requested priority imgrequest.m_requestedPriority = newRequest.Priority; //Assign the asset uuid imgrequest.m_requestedUUID = newRequest.RequestedAssetID; m_imagestore.Add(imgrequest.m_requestedUUID, imgrequest); //Run an update imgrequest.RunUpdate(); } } }
public void EnqueueReq(TextureRequestArgs newRequest) { //newRequest is the properties of our new texture fetch request. //Basically, here is where we queue up "new" requests.. // .. or modify existing requests to suit. //Make sure we're not shutting down.. if (!m_shuttingdown) { //Do we already know about this UUID? if (m_imagestore.ContainsKey(newRequest.RequestedAssetID)) { //Check the packet sequence to make sure this isn't older than //one we've already received J2KImage imgrequest = m_imagestore[newRequest.RequestedAssetID]; if (newRequest.requestSequence > imgrequest.m_lastSequence) { imgrequest.m_lastSequence = newRequest.requestSequence; //First of all, is this being killed? //if (newRequest.Priority == 0.0f && newRequest.DiscardLevel == -1) //{ //Do nothing (leaving the if for future use) //} //else //{ //Check the priority double priority = imgrequest.m_requestedPriority; if (priority != newRequest.Priority) { //Remove the old priority m_priorities.Remove(imgrequest.m_designatedPriorityKey); //Assign a new unique priority imgrequest.m_requestedPriority = newRequest.Priority; imgrequest.m_designatedPriorityKey = AssignPriority(newRequest.RequestedAssetID, newRequest.Priority); } //Update the requested discard level imgrequest.m_requestedDiscardLevel = newRequest.DiscardLevel; //Update the requested packet number imgrequest.m_requestedPacketNumber = newRequest.PacketNumber; //Check if this will create an outstanding texture request bool activated = imgrequest.m_completedSendAtCurrentDiscardLevel; //Run an update imgrequest.RunUpdate(); if (activated && !imgrequest.m_completedSendAtCurrentDiscardLevel && imgrequest.m_decoded) { m_outstandingtextures++; } //} } } else { J2KImage imgrequest = new J2KImage(this); //Assign our missing substitute imgrequest.m_MissingSubstitute = m_missingsubstitute; //Assign our decoder module imgrequest.m_j2kDecodeModule = m_j2kDecodeModule; //Assign our asset cache module imgrequest.m_assetCache = m_assetCache; //Assign a priority based on our request imgrequest.m_designatedPriorityKey = AssignPriority(newRequest.RequestedAssetID, newRequest.Priority); //Assign the requested discard level imgrequest.m_requestedDiscardLevel = newRequest.DiscardLevel; //Assign the requested packet number imgrequest.m_requestedPacketNumber = newRequest.PacketNumber; //Assign the requested priority imgrequest.m_requestedPriority = newRequest.Priority; //Assign the asset uuid imgrequest.m_requestedUUID = newRequest.RequestedAssetID; m_imagestore.Add(imgrequest.m_requestedUUID, imgrequest); //Run an update imgrequest.RunUpdate(); } } }
/// <summary> /// Handles an incoming texture request or update to an existing texture request /// </summary> /// <param name="newRequest"></param> public void EnqueueReq(TextureRequestArgs newRequest) { //Make sure we're not shutting down.. if (!m_shuttingdown) { J2KImage imgrequest; // 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) { if (newRequest.DiscardLevel == -1 && newRequest.Priority == 0f) { //m_log.Debug("[TEX]: (CAN) ID=" + newRequest.RequestedAssetID); try { lock (m_syncRoot) m_priorityQueue.Delete(imgrequest.PriorityQueueHandle); } catch (Exception) { } } else { //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 if (newRequest.requestSequence > imgrequest.LastSequence) { //Update the sequence number of the last RequestImage packet imgrequest.LastSequence = newRequest.requestSequence; //Update the requested discard level imgrequest.DiscardLevel = newRequest.DiscardLevel; //Update the requested packet number imgrequest.StartPacket = Math.Max(1, newRequest.PacketNumber); //Update the requested priority imgrequest.Priority = newRequest.Priority; UpdateImageInQueue(imgrequest); //Run an update imgrequest.RunUpdate(); } } } else { if (newRequest.DiscardLevel == -1 && newRequest.Priority == 0f) { //m_log.DebugFormat("[TEX]: (IGN) ID={0}: D={1}, S={2}, P={3}", // newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority); } else { //m_log.DebugFormat("[TEX]: (NEW) ID={0}: D={1}, S={2}, P={3}", // newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority); imgrequest = new J2KImage(this); imgrequest.J2KDecoder = m_j2kDecodeModule; imgrequest.AssetService = m_assetCache; imgrequest.AgentID = m_client.AgentId; imgrequest.InventoryAccessModule = m_client.Scene.RequestModuleInterface <IInventoryAccessModule>(); imgrequest.DiscardLevel = newRequest.DiscardLevel; imgrequest.StartPacket = Math.Max(1, newRequest.PacketNumber); imgrequest.Priority = newRequest.Priority; imgrequest.TextureID = newRequest.RequestedAssetID; imgrequest.Priority = newRequest.Priority; //Add this download to the priority queue AddImageToQueue(imgrequest); //Run an update imgrequest.RunUpdate(); } } } }
/// <summary> /// Handles an incoming texture request or update to an existing texture request /// </summary> /// <param name="newRequest"></param> public void EnqueueReq(TextureRequestArgs newRequest) { if (!m_shuttingdown) { J2KImage imgrequest; // 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) { if (newRequest.DiscardLevel < 0) { //m_log.Debug("[TEX]: (CAN) ID=" + newRequest.RequestedAssetID); try { lock (m_syncRoot) m_priorityQueue.Delete(imgrequest.PriorityQueueHandle); } catch (Exception) { } } else { // m_log.DebugFormat( // "[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); //Check the packet sequence to make sure this isn't older than //one we've already received if (newRequest.requestSequence > imgrequest.LastSequence) { //Update the sequence number of the last RequestImage packet imgrequest.LastSequence = newRequest.requestSequence; //Update the requested discard level imgrequest.DiscardLevel = newRequest.DiscardLevel; //Update the requested packet number imgrequest.StartPacket = Math.Max(1, newRequest.PacketNumber); //Update the requested priority imgrequest.Priority = newRequest.Priority; UpdateImageInQueue(imgrequest); imgrequest.RunUpdate(); // J2KImage imgrequest2 = new J2KImage(this); // imgrequest2.J2KDecoder = m_j2kDecodeModule; // imgrequest2.AssetService = m_assetCache; // imgrequest2.AgentID = m_client.AgentId; // imgrequest2.InventoryAccessModule = m_client.Scene.RequestModuleInterface<IInventoryAccessModule>(); // imgrequest2.DiscardLevel = newRequest.DiscardLevel; // imgrequest2.StartPacket = Math.Max(1, newRequest.PacketNumber); // imgrequest2.Priority = newRequest.Priority; // imgrequest2.TextureID = newRequest.RequestedAssetID; // imgrequest2.Priority = newRequest.Priority; // // //Add this download to the priority queue // AddImageToQueue(imgrequest2); // // imgrequest2.RunUpdate(); } // else // { // m_log.DebugFormat( // "[LL IMAGE MANAGER]: Ignoring duplicate of existing request for {0} (sequence {1}) from {2} as its request sequence {3} is not greater", // newRequest.RequestedAssetID, imgrequest.LastSequence, m_client.Name, newRequest.requestSequence); // } } } else { if (newRequest.DiscardLevel < 0) { //m_log.DebugFormat("[TEX]: (IGN) ID={0}: D={1}, S={2}, P={3}", // newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority); } else { // m_log.DebugFormat( // "[LL IMAGE MANAGER]: Received request for {0}, start packet {1} from {2}", // newRequest.RequestedAssetID, newRequest.PacketNumber, m_client.Name); //m_log.DebugFormat("[TEX]: (NEW) ID={0}: D={1}, S={2}, P={3}", // newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority); imgrequest = new J2KImage(this); imgrequest.J2KDecoder = m_j2kDecodeModule; imgrequest.AssetService = m_assetCache; imgrequest.AgentID = Client.AgentId; imgrequest.InventoryAccessModule = Client.Scene.RequestModuleInterface <IInventoryAccessModule>(); imgrequest.DiscardLevel = newRequest.DiscardLevel; imgrequest.StartPacket = Math.Max(1, newRequest.PacketNumber); imgrequest.Priority = newRequest.Priority; imgrequest.TextureID = newRequest.RequestedAssetID; imgrequest.Priority = newRequest.Priority; //Add this download to the priority queue AddImageToQueue(imgrequest); imgrequest.RunUpdate(); } } } }