* refactor: move asynchronous scene object deletion to inventory queueing out to a separate class
							parent
							
								
									5eb433ae26
								
							
						
					
					
						commit
						941e20c463
					
				|  | @ -0,0 +1,146 @@ | |||
| /* | ||||
|  * Copyright (c) Contributors, http://opensimulator.org/ | ||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the OpenSim Project nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Reflection; | ||||
| using System.Timers; | ||||
| using log4net; | ||||
| using OpenMetaverse; | ||||
| using OpenMetaverse.Packets; | ||||
| using OpenSim.Framework; | ||||
| 
 | ||||
| namespace OpenSim.Region.Environment.Scenes | ||||
| {         | ||||
|     class DeleteToInventoryHolder | ||||
|     { | ||||
|         public DeRezObjectPacket DeRezPacket; | ||||
|         public EntityBase selectedEnt; | ||||
|         public IClientAPI remoteClient; | ||||
|         public SceneObjectGroup objectGroup; | ||||
|         public UUID folderID; | ||||
|         public bool permissionToDelete; | ||||
|     } | ||||
|      | ||||
|     /// <summary> | ||||
|     /// Asynchronously derez objects.  This is used to derez large number of objects to inventory without holding  | ||||
|     /// up the main client thread. | ||||
|     /// </summary> | ||||
|     public class AsyncSceneObjectGroupDeleter | ||||
|     {    | ||||
|         private static readonly ILog m_log | ||||
|             = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
|          | ||||
|         private Timer m_inventoryTicker;         | ||||
|         private readonly Queue<DeleteToInventoryHolder> m_inventoryDeletes = new Queue<DeleteToInventoryHolder>();         | ||||
|         private Scene m_scene; | ||||
|          | ||||
|         public AsyncSceneObjectGroupDeleter(Scene scene) | ||||
|         { | ||||
|             m_scene = scene; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Delete the given object from the scene | ||||
|         /// </summary> | ||||
|         public void DeleteToInventory( | ||||
|             DeRezObjectPacket DeRezPacket, UUID folderID, SceneObjectGroup objectGroup, IClientAPI remoteClient,  | ||||
|             EntityBase selectedEnt, bool permissionToDelete) | ||||
|         { | ||||
|             if (m_inventoryTicker != null) | ||||
|             { | ||||
|                 m_inventoryTicker.Stop(); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 m_inventoryTicker = new Timer(2000); | ||||
|                 m_inventoryTicker.AutoReset = false; | ||||
|                 m_inventoryTicker.Elapsed += InventoryRunDeleteTimer; | ||||
|             } | ||||
| 
 | ||||
|             lock (m_inventoryDeletes) | ||||
|             { | ||||
|                 DeleteToInventoryHolder dtis = new DeleteToInventoryHolder(); | ||||
|                 dtis.DeRezPacket = DeRezPacket; | ||||
|                 dtis.folderID = folderID; | ||||
|                 dtis.objectGroup = objectGroup; | ||||
|                 dtis.remoteClient = remoteClient; | ||||
|                 dtis.selectedEnt = selectedEnt; | ||||
|                 dtis.permissionToDelete = permissionToDelete; | ||||
| 
 | ||||
|                 m_inventoryDeletes.Enqueue(dtis); | ||||
|             } | ||||
| 
 | ||||
|             m_inventoryTicker.Start(); | ||||
|          | ||||
|             // Visually remove it, even if it isnt really gone yet. | ||||
|             if (permissionToDelete) | ||||
|                 objectGroup.FakeDeleteGroup(); | ||||
|         } | ||||
|          | ||||
|         private void InventoryRunDeleteTimer(object sender, ElapsedEventArgs e) | ||||
|         { | ||||
|             m_log.Info("Starting inventory send loop"); | ||||
|             while (InventoryDeQueueAndDelete() == true) | ||||
|             { | ||||
|                 m_log.Info("Returned item successfully, continuing..."); | ||||
|             } | ||||
|         }             | ||||
| 
 | ||||
|         private bool InventoryDeQueueAndDelete() | ||||
|         { | ||||
|             DeleteToInventoryHolder x = null; | ||||
| 
 | ||||
|             try | ||||
|             { | ||||
|                 lock (m_inventoryDeletes) | ||||
|                 { | ||||
|                     int left = m_inventoryDeletes.Count; | ||||
|                     if (left > 0) | ||||
|                     { | ||||
|                         m_log.InfoFormat("Sending deleted object to user's inventory, {0} item(s) remaining.", left); | ||||
|                         x = m_inventoryDeletes.Dequeue(); | ||||
|                         m_scene.DeleteToInventory( | ||||
|                             x.DeRezPacket, x.selectedEnt, x.remoteClient, x.objectGroup, x.folderID, x.permissionToDelete); | ||||
|                         return true; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             catch(Exception e) | ||||
|             { | ||||
|                 // We can't put the object group details in here since the root part may have disappeared (which is where these sit). | ||||
|                 // FIXME: This needs to be fixed. | ||||
|                 m_log.ErrorFormat( | ||||
|                     "[AGENT INVENTORY]: Queued deletion of scene object to agent {0} {1} failed: {2}", | ||||
|                     (x != null ? x.remoteClient.Name : "unavailable"), (x != null ? x.remoteClient.AgentId.ToString() : "unavailable"), e.ToString()); | ||||
|             } | ||||
| 
 | ||||
|             m_log.Info("No objects left in inventory delete queue."); | ||||
|             return false; | ||||
|         }         | ||||
|     } | ||||
| } | ||||
|  | @ -40,23 +40,15 @@ using OpenSim.Region.Environment.Interfaces; | |||
| 
 | ||||
| namespace OpenSim.Region.Environment.Scenes | ||||
| { | ||||
|     class DeleteToInventoryHolder | ||||
|     { | ||||
|         public DeRezObjectPacket DeRezPacket; | ||||
|         public EntityBase selectedEnt; | ||||
|         public IClientAPI remoteClient; | ||||
|         public SceneObjectGroup objectGroup; | ||||
|         public UUID folderID; | ||||
|         public bool permissionToDelete; | ||||
|     } | ||||
| 
 | ||||
|     public partial class Scene | ||||
|     { | ||||
|         private Timer m_inventoryTicker; | ||||
|         private readonly Queue<DeleteToInventoryHolder> m_inventoryDeletes = new Queue<DeleteToInventoryHolder>(); | ||||
| 
 | ||||
|         private static readonly ILog m_log | ||||
|             = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Allows asynchronous derezzing of objects from the scene into a client's inventory. | ||||
|         /// </summary> | ||||
|         private AsyncSceneObjectGroupDeleter m_asyncSceneObjectDeleter;     | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Start all the scripts in the scene which should be started. | ||||
|  | @ -1546,35 +1538,8 @@ namespace OpenSim.Region.Environment.Scenes | |||
| 
 | ||||
|                     if (permissionToTake) | ||||
|                     { | ||||
|                         if (m_inventoryTicker != null) | ||||
|                         { | ||||
|                             m_inventoryTicker.Stop(); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             m_inventoryTicker = new Timer(2000); | ||||
|                             m_inventoryTicker.AutoReset = false; | ||||
|                             m_inventoryTicker.Elapsed += InventoryRunDeleteTimer; | ||||
|                         } | ||||
| 
 | ||||
|                         lock (m_inventoryDeletes) | ||||
|                         { | ||||
|                             DeleteToInventoryHolder dtis = new DeleteToInventoryHolder(); | ||||
|                             dtis.DeRezPacket = DeRezPacket; | ||||
|                             dtis.folderID = folderID; | ||||
|                             dtis.objectGroup = objectGroup; | ||||
|                             dtis.remoteClient = remoteClient; | ||||
|                             dtis.selectedEnt = selectedEnt; | ||||
|                             dtis.permissionToDelete = permissionToDelete; | ||||
| 
 | ||||
|                             m_inventoryDeletes.Enqueue(dtis); | ||||
|                         } | ||||
| 
 | ||||
|                         m_inventoryTicker.Start(); | ||||
| 
 | ||||
|                         // Visually remove it, even if it isnt really gone yet. | ||||
|                         if (permissionToDelete) | ||||
|                             objectGroup.FakeDeleteGroup(); | ||||
|                         m_asyncSceneObjectDeleter.DeleteToInventory( | ||||
|                             DeRezPacket, folderID, objectGroup, remoteClient, selectedEnt, permissionToDelete); | ||||
|                     } | ||||
|                     else if (permissionToDelete) | ||||
|                     { | ||||
|  | @ -1584,47 +1549,17 @@ namespace OpenSim.Region.Environment.Scenes | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         void InventoryRunDeleteTimer(object sender, ElapsedEventArgs e) | ||||
|         { | ||||
|             m_log.Info("Starting inventory send loop"); | ||||
|             while (InventoryDeQueueAndDelete() == true) | ||||
|             { | ||||
|                 m_log.Info("Returned item successfully, continuing..."); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private bool InventoryDeQueueAndDelete() | ||||
|         { | ||||
|             DeleteToInventoryHolder x = null; | ||||
| 
 | ||||
|             try | ||||
|             { | ||||
|                 lock (m_inventoryDeletes) | ||||
|                 { | ||||
|                     int left = m_inventoryDeletes.Count; | ||||
|                     if (left > 0) | ||||
|                     { | ||||
|                         m_log.InfoFormat("Sending deleted object to user's inventory, {0} item(s) remaining.", left); | ||||
|                         x = m_inventoryDeletes.Dequeue(); | ||||
|                         DeleteToInventory(x.DeRezPacket, x.selectedEnt, x.remoteClient, x.objectGroup, x.folderID, x.permissionToDelete); | ||||
|                         return true; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             catch(Exception e) | ||||
|             { | ||||
|                 // We can't put the object group details in here since the root part may have disappeared (which is where these sit). | ||||
|                 // FIXME: This needs to be fixed. | ||||
|                 m_log.ErrorFormat( | ||||
|                     "[AGENT INVENTORY]: Queued deletion of scene object to agent {0} {1} failed: {2}", | ||||
|                     (x != null ? x.remoteClient.Name : "unavailable"), (x != null ? x.remoteClient.AgentId.ToString() : "unavailable"), e.ToString()); | ||||
|             } | ||||
| 
 | ||||
|             m_log.Info("No objects left in inventory delete queue."); | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         private void DeleteToInventory(DeRezObjectPacket DeRezPacket, EntityBase selectedEnt, IClientAPI remoteClient, SceneObjectGroup objectGroup, UUID folderID, bool permissionToDelete) | ||||
|         /// <summary> | ||||
|         /// Delete a scene object from a scene and place in the given avatar's inventory. | ||||
|         /// </summary> | ||||
|         /// <param name="DeRezPacket"></param> | ||||
|         /// <param name="selectedEnt"></param> | ||||
|         /// <param name="remoteClient"> </param> | ||||
|         /// <param name="objectGroup"></param> | ||||
|         /// <param name="folderID"></param> | ||||
|         /// <param name="permissionToDelete"></param> | ||||
|         public void DeleteToInventory(DeRezObjectPacket DeRezPacket, EntityBase selectedEnt, IClientAPI remoteClient,  | ||||
|             SceneObjectGroup objectGroup, UUID folderID, bool permissionToDelete) | ||||
|         { | ||||
|             string sceneObjectXml = objectGroup.ToXmlString(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -275,6 +275,7 @@ namespace OpenSim.Region.Environment.Scenes | |||
| 
 | ||||
|             m_eventManager = new EventManager(); | ||||
|             m_externalChecks = new SceneExternalChecks(this); | ||||
|             m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);     | ||||
| 
 | ||||
|             // Load region settings | ||||
|             m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Justin Clarke Casey
						Justin Clarke Casey