CMModel.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSim Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #region Header
  28. // CMModel.cs
  29. // User: bongiojp
  30. //
  31. //
  32. #endregion Header
  33. using System;
  34. using System.Collections;
  35. using System.Collections.Generic;
  36. using System.Diagnostics;
  37. using OpenMetaverse;
  38. using OpenSim;
  39. using OpenSim.Framework;
  40. using OpenSim.Region.Environment.Interfaces;
  41. using OpenSim.Region.Environment.Scenes;
  42. using OpenSim.Region.Physics.Manager;
  43. using log4net;
  44. namespace OpenSim.Region.Environment.Modules.ContentManagement
  45. {
  46. public class CMModel
  47. {
  48. #region Static Fields
  49. static float TimeToUpdate = 0;
  50. static float TimeToConvertXml = 0;
  51. private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
  52. #endregion Static Fields
  53. #region Fields
  54. /// <value>
  55. /// The class that contains all auras and metaentities used in the CMS.
  56. /// </value>
  57. CMEntityCollection m_MetaEntityCollection = new CMEntityCollection();
  58. IContentDatabase m_database = null;
  59. #endregion Fields
  60. #region Constructors
  61. public CMModel()
  62. {
  63. }
  64. #endregion Constructors
  65. #region Public Properties
  66. public CMEntityCollection MetaEntityCollection
  67. {
  68. get { return m_MetaEntityCollection; }
  69. }
  70. #endregion Public Properties
  71. #region Public Methods
  72. /// <summary>
  73. /// 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
  74. /// it is a new part that must have a green aura (for diff mode).
  75. /// Returns list of ContentManagementEntities
  76. /// </summary>
  77. public ArrayList CheckForNewEntitiesMissingAuras(Scene scene)
  78. {
  79. ArrayList missingList = null;
  80. ArrayList newList = new ArrayList();
  81. m_log.Debug("[CONTENT MANAGEMENT] Checking for new scene object parts in scene: " + scene.RegionInfo.RegionName);
  82. //Check if the current scene has groups not included in the current list of MetaEntities
  83. //If so, then the current scene's parts that are new should be marked green.
  84. missingList = m_MetaEntityCollection.CheckForMissingEntities(scene.GetEntities());
  85. foreach (Object missingPart in missingList)
  86. {
  87. if (m_MetaEntityCollection.Auras.ContainsKey(((SceneObjectPart)missingPart).UUID))
  88. continue;
  89. newList.Add(m_MetaEntityCollection.CreateAuraForNewlyCreatedEntity((SceneObjectPart)missingPart));
  90. }
  91. m_log.Info("Number of missing objects found: " + newList.Count);
  92. return newList;
  93. }
  94. /// <summary>
  95. /// Uses the database to serialize all current scene objects into xml and save into a database with an accompanying log message.
  96. /// </summary>
  97. public void CommitRegion(Scene scene, String logMessage)
  98. {
  99. m_log.Debug("[CONTENT MANAG] saving " + scene.RegionInfo.RegionName + " with log message: " + logMessage + " length of message: " + logMessage.Length);
  100. m_database.SaveRegion(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, logMessage);
  101. m_log.Debug("[CONTENT MANAG] the region name we are dealing with heeeeeeeere: " + scene.RegionInfo.RegionName );
  102. }
  103. public void DeleteAllMetaObjects()
  104. {
  105. m_MetaEntityCollection.ClearAll();
  106. }
  107. public ContentManagementEntity FindMetaEntityAffectedByUndo(UUID uuid)
  108. {
  109. ContentManagementEntity ent = GetMetaGroupByPrim(uuid);
  110. return ent;
  111. }
  112. //-------------------------------- HELPERS --------------------------------------------------------------------//
  113. public ContentManagementEntity GetMetaGroupByPrim(UUID uuid)
  114. {
  115. foreach (Object ent in m_MetaEntityCollection.Entities.Values)
  116. {
  117. if (((ContentManagementEntity)ent).HasChildPrim(uuid))
  118. return (ContentManagementEntity)ent;
  119. }
  120. return null;
  121. }
  122. public void Initialise(string database)
  123. {
  124. if (database == "FileSystemDatabase")
  125. m_database = new FileSystemDatabase();
  126. else if (database == "GitDatabase")
  127. m_database = new GitDatabase();
  128. }
  129. public void InitialiseDatabase(Scene scene, string dir)
  130. {
  131. m_database.Initialise(scene, dir);
  132. }
  133. /// <summary>
  134. /// Should be called just once to finish initializing the database.
  135. /// </summary>
  136. public void PostInitialise()
  137. {
  138. m_database.PostInitialise();
  139. }
  140. /// <summary>
  141. /// Removes the green aura when an a new scene object group is deleted.
  142. /// </summary>
  143. public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group)
  144. {
  145. // Deal with new parts not revisioned that have been deleted.
  146. foreach (SceneObjectPart part in group.Children.Values)
  147. if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID))
  148. m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(part.UUID);
  149. }
  150. /// <summary>
  151. /// Retrieves the latest revision of a region in xml form,
  152. /// converts it to scene object groups and scene presences,
  153. /// swaps the current scene's entity list with the revision's list.
  154. /// Note: Since deleted objects while
  155. /// </summary>
  156. public void RollbackRegion(Scene scene)
  157. {
  158. System.Collections.ArrayList xmllist = null;
  159. SceneObjectGroup temp = null;
  160. System.Collections.Hashtable deleteListUUIDs = new Hashtable();
  161. // Dictionary<LLUUID, EntityBase> SearchList = new Dictionary<LLUUID,EntityBase>();
  162. Dictionary<UUID, EntityBase> ReplacementList = new Dictionary<UUID,EntityBase>();
  163. int revision = m_database.GetMostRecentRevision(scene.RegionInfo.RegionID);
  164. // EntityBase[] searchArray;
  165. xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID, revision);
  166. if (xmllist == null)
  167. {
  168. m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") does not have given revision number (" + revision + ").");
  169. return;
  170. }
  171. m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") revision number (" + revision + ").");
  172. m_log.Info("[CMMODEL]: Scene Objects = " + xmllist.Count);
  173. m_log.Info("[CMMODEL]: Converting scene entities list to specified revision.");
  174. m_log.ErrorFormat("[CMMODEL]: 1");
  175. foreach (string xml in xmllist)
  176. {
  177. try{
  178. temp = new SceneObjectGroup(xml);
  179. temp.SetScene(scene);
  180. foreach (SceneObjectPart part in temp.Children.Values)
  181. part.RegionHandle = scene.RegionInfo.RegionHandle;
  182. ReplacementList.Add(temp.UUID, (EntityBase)temp);
  183. }
  184. catch(Exception e)
  185. {
  186. m_log.Info("[CMMODEL]: Error while creating replacement list for rollback: " + e);
  187. }
  188. }
  189. //If in scene but not in revision and not a client, remove them
  190. while (true)
  191. {
  192. try
  193. {
  194. foreach (EntityBase entity in scene.GetEntities())
  195. {
  196. if (entity == null)
  197. continue;
  198. if (entity is ScenePresence)
  199. {
  200. ReplacementList.Add(entity.UUID, entity);
  201. continue;
  202. }
  203. else //if (!ReplacementList.ContainsKey(entity.UUID))
  204. deleteListUUIDs.Add(entity.UUID, 0);
  205. }
  206. }
  207. catch(Exception e)
  208. {
  209. m_log.ErrorFormat("[CMMODEL]: " + e);
  210. deleteListUUIDs.Clear();
  211. ReplacementList.Clear();
  212. continue;
  213. }
  214. break;
  215. }
  216. foreach (UUID uuid in deleteListUUIDs.Keys)
  217. {
  218. try
  219. {
  220. // I thought that the DeleteGroup() function would handle all of this, but it doesn't. I'm not sure WHAT it handles.
  221. ((SceneObjectGroup)scene.Entities[uuid]).DetachFromBackup();
  222. scene.PhysicsScene.RemovePrim(((SceneObjectGroup)scene.Entities[uuid]).RootPart.PhysActor);
  223. scene.SendKillObject(scene.Entities[uuid].LocalId);
  224. scene.m_sceneGraph.DeleteSceneObject(uuid, false);
  225. ((SceneObjectGroup)scene.Entities[uuid]).DeleteGroup(false);
  226. }
  227. catch(Exception e)
  228. {
  229. m_log.ErrorFormat("[CMMODEL]: Error while removing objects from scene: " + e);
  230. }
  231. }
  232. lock (scene)
  233. {
  234. scene.Entities.Clear();
  235. foreach (KeyValuePair<UUID,EntityBase> kvp in ReplacementList)
  236. {
  237. scene.Entities.Add(kvp.Value);
  238. }
  239. }
  240. foreach (EntityBase ent in ReplacementList.Values)
  241. {
  242. try
  243. {
  244. if (!(ent is SceneObjectGroup))
  245. continue;
  246. if ((((SceneObjectGroup)ent).RootPart.GetEffectiveObjectFlags() & (uint) PrimFlags.Phantom) == 0)
  247. ((SceneObjectGroup)ent).ApplyPhysics(true);
  248. ((SceneObjectGroup)ent).AttachToBackup();
  249. ((SceneObjectGroup)ent).HasGroupChanged = true; // If not true, then attaching to backup does nothing because no change is detected.
  250. ((SceneObjectGroup)ent).ScheduleGroupForFullUpdate();
  251. }
  252. catch(Exception e)
  253. {
  254. m_log.ErrorFormat("[CMMODEL]: Error while attaching new scene entities to backup and scheduling for a full update: " + e);
  255. }
  256. }
  257. m_log.Info("[CMMODEL]: Scheduling a backup of new scene object groups to backup.");
  258. scene.Backup();
  259. }
  260. /// <summary>
  261. /// Downloads the latest revision of the given scene and converts the xml file to CMEntities. After this method, the view can find the differences
  262. /// and display the differences to clients.
  263. /// </summary>
  264. public void UpdateCMEntities(Scene scene)
  265. {
  266. Stopwatch x = new Stopwatch();
  267. x.Start();
  268. System.Collections.ArrayList xmllist = null;
  269. m_log.Debug("[CONTENT MANAGEMENT] Retrieving object xml files for region: " + scene.RegionInfo.RegionID);
  270. xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID);
  271. m_log.Info("[FSDB]: got list");
  272. if (xmllist == null)
  273. return;
  274. Stopwatch y = new Stopwatch();
  275. y.Start();
  276. foreach (string xml in xmllist)
  277. m_MetaEntityCollection.CreateNewEntity(xml, scene);
  278. y.Stop();
  279. TimeToConvertXml += y.ElapsedMilliseconds;
  280. m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities for " + scene.RegionInfo.RegionName + ": " + y.ElapsedMilliseconds);
  281. m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities so far: " + TimeToConvertXml);
  282. m_log.Info("[FSDB]: checking for new scene object parts missing green auras and create the auras");
  283. CheckForNewEntitiesMissingAuras(scene);
  284. x.Stop();
  285. TimeToUpdate += x.ElapsedMilliseconds;
  286. m_log.Info("[FileSystemDatabase] Time spent Updating entity list for " + scene.RegionInfo.RegionName + ": " + x.ElapsedMilliseconds);
  287. m_log.Info("[FileSystemDatabase] Time spent Updating so far: " + TimeToUpdate);
  288. }
  289. /// <summary>
  290. /// Detects if a scene object group from the scene list has moved or changed scale. The green aura
  291. /// that surrounds the object is then moved or scaled with the group.
  292. /// </summary>
  293. public System.Collections.ArrayList UpdateNormalEntityEffects(SceneObjectGroup group)
  294. {
  295. System.Collections.ArrayList auraList = new System.Collections.ArrayList();
  296. if (group == null)
  297. return null;
  298. foreach (SceneObjectPart part in group.Children.Values)
  299. {
  300. if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID))
  301. {
  302. ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new Vector3(0,254,0), part.Scale);
  303. ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition();
  304. auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]);
  305. }
  306. }
  307. return auraList;
  308. }
  309. #endregion Public Methods
  310. }
  311. }