From 12beaccec79319186ae2a7bf3663510584117a63 Mon Sep 17 00:00:00 2001 From: Sean Dague Date: Wed, 3 Sep 2008 18:04:37 +0000 Subject: Merge branch 'cms' of http://pokgsa.ibm.com/~jbongio/public/opensim --- .../Modules/ContentManagementSystem/CMModel.cs | 309 +++++++++++++++++++++ 1 file changed, 309 insertions(+) create mode 100644 OpenSim/Region/Environment/Modules/ContentManagementSystem/CMModel.cs (limited to 'OpenSim/Region/Environment/Modules/ContentManagementSystem/CMModel.cs') diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMModel.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMModel.cs new file mode 100644 index 0000000..d3b3b77 --- /dev/null +++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMModel.cs @@ -0,0 +1,309 @@ +// CMModel.cs +// User: bongiojp +// +// + +using System; +using System.Collections.Generic; +using System.Collections; +using libsecondlife; +using OpenSim; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using log4net; +using OpenSim.Region.Physics.Manager; +using Axiom.Math; +using System.Diagnostics; + +namespace OpenSim.Region.Environment.Modules.ContentManagement +{ + + public class CMModel + { + static float TimeToUpdate = 0; + static float TimeToConvertXml = 0; + + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + IContentDatabase m_database = null; + + /// + /// The class that contains all auras and metaentities used in the CMS. + /// + CMEntityCollection m_MetaEntityCollection = new CMEntityCollection(); + + public CMEntityCollection MetaEntityCollection + { + get { return m_MetaEntityCollection; } + } + + public CMModel() + { + } + + public void Initialise(string database) + { + if (database == "FileSystemDatabase") + m_database = new FileSystemDatabase(); + else if (database == "GitDatabase") + m_database = new GitDatabase(); + } + + public void InitialiseDatabase(Scene scene, string dir) + { + m_database.Initialise(scene, dir); + } + + /// + /// Should be called just once to finish initializing the database. + /// + public void PostInitialise() + { + m_database.PostInitialise(); + } + + public ContentManagementEntity FindMetaEntityAffectedByUndo(LLUUID uuid) + { + ContentManagementEntity ent = GetMetaGroupByPrim(uuid); + return ent; + } + + /// + /// Removes the green aura when an a new scene object group is deleted. + /// + public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group) + { + // Deal with new parts not revisioned that have been deleted. + foreach(SceneObjectPart part in group.Children.Values) + if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) + m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(part.UUID); + } + + /// + /// Uses the database to serialize all current scene objects into xml and save into a database with an accompanying log message. + /// + public void CommitRegion(Scene scene, String logMessage) + { + m_log.Debug("[CONTENT MANAG] saving " + scene.RegionInfo.RegionName + " with log message: " + logMessage + " length of message: " + logMessage.Length); + m_database.SaveRegion(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, logMessage); + m_log.Debug("[CONTENT MANAG] the region name we are dealing with heeeeeeeere: " + scene.RegionInfo.RegionName ); + } + + /// + /// Retrieves the latest revision of a region in xml form, + /// converts it to scene object groups and scene presences, + /// swaps the current scene's entity list with the revision's list. + /// Note: Since deleted objects while + /// + public void RollbackRegion(Scene scene) + { + System.Collections.ArrayList xmllist = null; + SceneObjectGroup temp = null; + System.Collections.Hashtable deleteListUUIDs = new Hashtable(); + Dictionary SearchList = new Dictionary(); + Dictionary ReplacementList = new Dictionary(); + int revision = m_database.GetMostRecentRevision(scene.RegionInfo.RegionID); + EntityBase[] searchArray; + + xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID, revision); + if (xmllist == null) + { + m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") does not have given revision number (" + revision + ")."); + return; + } + + m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") revision number (" + revision + ")."); + m_log.Info("[CMMODEL]: Scene Objects = " + xmllist.Count); + m_log.Info("[CMMODEL]: Converting scene entities list to specified revision."); + + m_log.ErrorFormat("[CMMODEL]: 1"); + + foreach (string xml in xmllist) + { + try{ + temp = new SceneObjectGroup(xml); + temp.SetScene(scene); + foreach(SceneObjectPart part in temp.Children.Values) + part.RegionHandle = scene.RegionInfo.RegionHandle; + ReplacementList.Add(temp.UUID, (EntityBase)temp); + } + catch(Exception e) + { + m_log.Info("[CMMODEL]: Error while creating replacement list for rollback: " + e); + } + } + + //If in scene but not in revision and not a client, remove them + while (true) + { + try + { + foreach(EntityBase entity in scene.GetEntities()) + { + if (entity == null) + continue; + + if (entity is ScenePresence) + { + ReplacementList.Add(entity.UUID, entity); + continue; + } + else //if (!ReplacementList.ContainsKey(entity.UUID)) + deleteListUUIDs.Add(entity.UUID, 0); + } + } + catch(Exception e) + { + m_log.ErrorFormat("[CMMODEL]: " + e); + deleteListUUIDs.Clear(); + ReplacementList.Clear(); + continue; + } + break; + } + + foreach(LLUUID uuid in deleteListUUIDs.Keys) + { + try + { + // I thought that the DeleteGroup() function would handle all of this, but it doesn't. I'm not sure WHAT it handles. + ((SceneObjectGroup)scene.Entities[uuid]).DetachFromBackup((SceneObjectGroup)scene.Entities[uuid]); + scene.PhysicsScene.RemovePrim(((SceneObjectGroup)scene.Entities[uuid]).RootPart.PhysActor); + scene.SendKillObject(scene.Entities[uuid].LocalId); + scene.m_innerScene.DeleteSceneObject(uuid, false); + ((SceneObjectGroup)scene.Entities[uuid]).DeleteGroup(); + } + catch(Exception e) + { + m_log.ErrorFormat("[CMMODEL]: Error while removing objects from scene: " + e); + } + } + + lock (scene) + { + scene.Entities = ReplacementList; + } + + foreach(EntityBase ent in ReplacementList.Values) + { + try + { + if (!(ent is SceneObjectGroup)) + continue; + + if ((((SceneObjectGroup)ent).RootPart.GetEffectiveObjectFlags() & (uint) LLObject.ObjectFlags.Phantom) == 0) + ((SceneObjectGroup)ent).ApplyPhysics(true); + ((SceneObjectGroup)ent).AttachToBackup(); + ((SceneObjectGroup)ent).HasGroupChanged = true; // If not true, then attaching to backup does nothing because no change is detected. + ((SceneObjectGroup)ent).ScheduleGroupForFullUpdate(); + } + catch(Exception e) + { + m_log.ErrorFormat("[CMMODEL]: Error while attaching new scene entities to backup and scheduling for a full update: " + e); + } + } + m_log.Info("[CMMODEL]: Scheduling a backup of new scene object groups to backup."); + scene.Backup(); + } + + /// + /// Detects if a scene object group from the scene list has moved or changed scale. The green aura + /// that surrounds the object is then moved or scaled with the group. + /// + public System.Collections.ArrayList UpdateNormalEntityEffects(SceneObjectGroup group) + { + System.Collections.ArrayList auraList = new System.Collections.ArrayList(); + if (group == null) + return null; + foreach(SceneObjectPart part in group.Children.Values) + { + if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) + { + ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new LLVector3(0,254,0), part.Scale); + ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition(); + auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]); + } + } + return auraList; + } + + public void DeleteAllMetaObjects() + { + m_MetaEntityCollection.ClearAll(); + } + + /// + /// Downloads the latest revision of the given scene and converts the xml file to CMEntities. After this method, the view can find the differences + /// and display the differences to clients. + /// + public void UpdateCMEntities(Scene scene) + { + Stopwatch x = new Stopwatch(); + x.Start(); + + System.Collections.ArrayList xmllist = null; + m_log.Debug("[CONTENT MANAGEMENT] Retrieving object xml files for region: " + scene.RegionInfo.RegionID); + xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID); + m_log.Info("[FSDB]: got list"); + if (xmllist == null) + return; + + Stopwatch y = new Stopwatch(); + y.Start(); + foreach (string xml in xmllist) + m_MetaEntityCollection.CreateNewEntity(xml, scene); + y.Stop(); + TimeToConvertXml += y.ElapsedMilliseconds; + m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities for " + scene.RegionInfo.RegionName + ": " + y.ElapsedMilliseconds); + m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities so far: " + TimeToConvertXml); + + m_log.Info("[FSDB]: checking for new scene object parts missing green auras and create the auras"); + CheckForNewEntitiesMissingAuras(scene); + + x.Stop(); + TimeToUpdate += x.ElapsedMilliseconds; + m_log.Info("[FileSystemDatabase] Time spent Updating entity list for " + scene.RegionInfo.RegionName + ": " + x.ElapsedMilliseconds); + m_log.Info("[FileSystemDatabase] Time spent Updating so far: " + TimeToUpdate); + + } + + /// + /// Compares the scene's object group list to the list of meta entities. If there is an object group that does not have a corresponding meta entity + /// it is a new part that must have a green aura (for diff mode). + /// Returns list of ContentManagementEntities + /// + public ArrayList CheckForNewEntitiesMissingAuras(Scene scene) + { + ArrayList missingList = null; + ArrayList newList = new ArrayList(); + + m_log.Debug("[CONTENT MANAGEMENT] Checking for new scene object parts in scene: " + scene.RegionInfo.RegionName); + + //Check if the current scene has groups not included in the current list of MetaEntities + //If so, then the current scene's parts that are new should be marked green. + missingList = m_MetaEntityCollection.CheckForMissingEntities(scene.GetEntities()); + + foreach(Object missingPart in missingList) + { + if (m_MetaEntityCollection.Auras.ContainsKey(((SceneObjectPart)missingPart).UUID)) + continue; + newList.Add(m_MetaEntityCollection.CreateAuraForNewlyCreatedEntity((SceneObjectPart)missingPart)); + } + m_log.Info("Number of missing objects found: " + newList.Count); + return newList; + } + +//-------------------------------- HELPERS --------------------------------------------------------------------// + + public ContentManagementEntity GetMetaGroupByPrim(LLUUID uuid) + { + foreach (Object ent in m_MetaEntityCollection.Entities.Values) + { + if (((ContentManagementEntity)ent).HasChildPrim(uuid)) + return (ContentManagementEntity)ent; + } + return null; + } + } +} \ No newline at end of file -- cgit v1.1