CMModel.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  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 OpenSimulator 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. using System;
  28. using System.Collections;
  29. using System.Collections.Generic;
  30. using System.Diagnostics;
  31. using OpenMetaverse;
  32. using OpenSim;
  33. using OpenSim.Framework;
  34. using OpenSim.Region.Framework.Interfaces;
  35. using OpenSim.Region.Framework.Scenes;
  36. using OpenSim.Region.Framework.Scenes.Serialization;
  37. using OpenSim.Region.Physics.Manager;
  38. using log4net;
  39. namespace OpenSim.Region.OptionalModules.ContentManagement
  40. {
  41. public class CMModel
  42. {
  43. #region Static Fields
  44. static float TimeToUpdate = 0;
  45. static float TimeToConvertXml = 0;
  46. private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
  47. #endregion Static Fields
  48. #region Fields
  49. /// <value>
  50. /// The class that contains all auras and metaentities used in the CMS.
  51. /// </value>
  52. CMEntityCollection m_MetaEntityCollection = new CMEntityCollection();
  53. IContentDatabase m_database = null;
  54. #endregion Fields
  55. #region Constructors
  56. public CMModel()
  57. {
  58. }
  59. #endregion Constructors
  60. #region Public Properties
  61. public CMEntityCollection MetaEntityCollection
  62. {
  63. get { return m_MetaEntityCollection; }
  64. }
  65. #endregion Public Properties
  66. #region Public Methods
  67. /// <summary>
  68. /// 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
  69. /// it is a new part that must have a green aura (for diff mode).
  70. /// Returns list of ContentManagementEntities
  71. /// </summary>
  72. public ArrayList CheckForNewEntitiesMissingAuras(Scene scene)
  73. {
  74. ArrayList missingList = null;
  75. ArrayList newList = new ArrayList();
  76. m_log.Debug("[CONTENT MANAGEMENT] Checking for new scene object parts in scene: " + scene.RegionInfo.RegionName);
  77. //Check if the current scene has groups not included in the current list of MetaEntities
  78. //If so, then the current scene's parts that are new should be marked green.
  79. missingList = m_MetaEntityCollection.CheckForMissingEntities(scene.GetEntities());
  80. foreach (Object missingPart in missingList)
  81. {
  82. if (m_MetaEntityCollection.Auras.ContainsKey(((SceneObjectPart)missingPart).UUID))
  83. continue;
  84. newList.Add(m_MetaEntityCollection.CreateAuraForNewlyCreatedEntity((SceneObjectPart)missingPart));
  85. }
  86. m_log.Info("Number of missing objects found: " + newList.Count);
  87. return newList;
  88. }
  89. /// <summary>
  90. /// Uses the database to serialize all current scene objects into xml and save into a database with an accompanying log message.
  91. /// </summary>
  92. public void CommitRegion(Scene scene, String logMessage)
  93. {
  94. m_log.Debug("[CONTENT MANAG] saving " + scene.RegionInfo.RegionName + " with log message: " + logMessage + " length of message: " + logMessage.Length);
  95. m_database.SaveRegion(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, logMessage);
  96. m_log.Debug("[CONTENT MANAG] the region name we are dealing with heeeeeeeere: " + scene.RegionInfo.RegionName);
  97. }
  98. public void DeleteAllMetaObjects()
  99. {
  100. m_MetaEntityCollection.ClearAll();
  101. }
  102. public ContentManagementEntity FindMetaEntityAffectedByUndo(UUID uuid)
  103. {
  104. ContentManagementEntity ent = GetMetaGroupByPrim(uuid);
  105. return ent;
  106. }
  107. //-------------------------------- HELPERS --------------------------------------------------------------------//
  108. public ContentManagementEntity GetMetaGroupByPrim(UUID uuid)
  109. {
  110. foreach (Object ent in m_MetaEntityCollection.Entities.Values)
  111. {
  112. if (((ContentManagementEntity)ent).HasChildPrim(uuid))
  113. return (ContentManagementEntity)ent;
  114. }
  115. return null;
  116. }
  117. public void Initialise(string database)
  118. {
  119. if (database == "FileSystemDatabase")
  120. m_database = new FileSystemDatabase();
  121. else if (database == "GitDatabase")
  122. m_database = new GitDatabase();
  123. }
  124. public void InitialiseDatabase(Scene scene, string dir)
  125. {
  126. m_database.Initialise(scene, dir);
  127. }
  128. /// <summary>
  129. /// Should be called just once to finish initializing the database.
  130. /// </summary>
  131. public void PostInitialise()
  132. {
  133. m_database.PostInitialise();
  134. }
  135. /// <summary>
  136. /// Removes the green aura when an a new scene object group is deleted.
  137. /// </summary>
  138. public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group)
  139. {
  140. // Deal with new parts not revisioned that have been deleted.
  141. lock (group.Children)
  142. {
  143. foreach (SceneObjectPart part in group.Children.Values)
  144. if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID))
  145. m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(part.UUID);
  146. }
  147. }
  148. /// <summary>
  149. /// Retrieves the latest revision of a region in xml form,
  150. /// converts it to scene object groups and scene presences,
  151. /// swaps the current scene's entity list with the revision's list.
  152. /// Note: Since deleted objects while
  153. /// </summary>
  154. public void RollbackRegion(Scene scene)
  155. {
  156. System.Collections.ArrayList xmllist = null;
  157. SceneObjectGroup temp = null;
  158. System.Collections.Hashtable deleteListUUIDs = new Hashtable();
  159. // Dictionary<LLUUID, EntityBase> SearchList = new Dictionary<LLUUID,EntityBase>();
  160. Dictionary<UUID, EntityBase> ReplacementList = new Dictionary<UUID,EntityBase>();
  161. int revision = m_database.GetMostRecentRevision(scene.RegionInfo.RegionID);
  162. // EntityBase[] searchArray;
  163. xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID, revision);
  164. if (xmllist == null)
  165. {
  166. m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") does not have given revision number (" + revision + ").");
  167. return;
  168. }
  169. m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") revision number (" + revision + ").");
  170. m_log.Info("[CMMODEL]: Scene Objects = " + xmllist.Count);
  171. m_log.Info("[CMMODEL]: Converting scene entities list to specified revision.");
  172. m_log.ErrorFormat("[CMMODEL]: 1");
  173. foreach (string xml in xmllist)
  174. {
  175. try
  176. {
  177. temp = SceneObjectSerializer.FromXml2Format(xml);
  178. temp.SetScene(scene);
  179. lock (temp.Children)
  180. {
  181. foreach (SceneObjectPart part in temp.Children.Values)
  182. part.RegionHandle = scene.RegionInfo.RegionHandle;
  183. }
  184. ReplacementList.Add(temp.UUID, (EntityBase)temp);
  185. }
  186. catch (Exception e)
  187. {
  188. m_log.Info("[CMMODEL]: Error while creating replacement list for rollback: " + e);
  189. }
  190. }
  191. //If in scene but not in revision and not a client, remove them
  192. while (true)
  193. {
  194. try
  195. {
  196. foreach (EntityBase entity in scene.GetEntities())
  197. {
  198. if (entity == null)
  199. continue;
  200. if (entity is ScenePresence)
  201. {
  202. ReplacementList.Add(entity.UUID, entity);
  203. continue;
  204. }
  205. else //if (!ReplacementList.ContainsKey(entity.UUID))
  206. deleteListUUIDs.Add(entity.UUID, 0);
  207. }
  208. }
  209. catch(Exception e)
  210. {
  211. m_log.ErrorFormat("[CMMODEL]: " + e);
  212. deleteListUUIDs.Clear();
  213. ReplacementList.Clear();
  214. continue;
  215. }
  216. break;
  217. }
  218. foreach (UUID uuid in deleteListUUIDs.Keys)
  219. {
  220. try
  221. {
  222. // I thought that the DeleteGroup() function would handle all of this, but it doesn't. I'm not sure WHAT it handles.
  223. ((SceneObjectGroup)scene.Entities[uuid]).DetachFromBackup();
  224. scene.PhysicsScene.RemovePrim(((SceneObjectGroup)scene.Entities[uuid]).RootPart.PhysActor);
  225. scene.SendKillObject(scene.Entities[uuid].LocalId);
  226. scene.SceneGraph.DeleteSceneObject(uuid, false);
  227. ((SceneObjectGroup)scene.Entities[uuid]).DeleteGroup(false);
  228. }
  229. catch(Exception e)
  230. {
  231. m_log.ErrorFormat("[CMMODEL]: Error while removing objects from scene: " + e);
  232. }
  233. }
  234. lock (scene)
  235. {
  236. scene.Entities.Clear();
  237. foreach (KeyValuePair<UUID,EntityBase> kvp in ReplacementList)
  238. {
  239. scene.Entities.Add(kvp.Value);
  240. }
  241. }
  242. foreach (EntityBase ent in ReplacementList.Values)
  243. {
  244. try
  245. {
  246. if (!(ent is SceneObjectGroup))
  247. continue;
  248. if ((((SceneObjectGroup)ent).RootPart.GetEffectiveObjectFlags() & (uint) PrimFlags.Phantom) == 0)
  249. ((SceneObjectGroup)ent).ApplyPhysics(true);
  250. ((SceneObjectGroup)ent).AttachToBackup();
  251. ((SceneObjectGroup)ent).HasGroupChanged = true; // If not true, then attaching to backup does nothing because no change is detected.
  252. ((SceneObjectGroup)ent).ScheduleGroupForFullUpdate();
  253. }
  254. catch(Exception e)
  255. {
  256. m_log.ErrorFormat("[CMMODEL]: Error while attaching new scene entities to backup and scheduling for a full update: " + e);
  257. }
  258. }
  259. m_log.Info("[CMMODEL]: Scheduling a backup of new scene object groups to backup.");
  260. scene.Backup(true);
  261. }
  262. /// <summary>
  263. /// Downloads the latest revision of the given scene and converts the xml file to CMEntities. After this method, the view can find the differences
  264. /// and display the differences to clients.
  265. /// </summary>
  266. public void UpdateCMEntities(Scene scene)
  267. {
  268. Stopwatch x = new Stopwatch();
  269. x.Start();
  270. System.Collections.ArrayList xmllist = null;
  271. m_log.Debug("[CONTENT MANAGEMENT] Retrieving object xml files for region: " + scene.RegionInfo.RegionID);
  272. xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID);
  273. m_log.Info("[FSDB]: got list");
  274. if (xmllist == null)
  275. return;
  276. Stopwatch y = new Stopwatch();
  277. y.Start();
  278. foreach (string xml in xmllist)
  279. m_MetaEntityCollection.CreateNewEntity(xml, scene);
  280. y.Stop();
  281. TimeToConvertXml += y.ElapsedMilliseconds;
  282. m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities for " + scene.RegionInfo.RegionName + ": " + y.ElapsedMilliseconds);
  283. m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities so far: " + TimeToConvertXml);
  284. m_log.Info("[FSDB]: checking for new scene object parts missing green auras and create the auras");
  285. CheckForNewEntitiesMissingAuras(scene);
  286. x.Stop();
  287. TimeToUpdate += x.ElapsedMilliseconds;
  288. m_log.Info("[FileSystemDatabase] Time spent Updating entity list for " + scene.RegionInfo.RegionName + ": " + x.ElapsedMilliseconds);
  289. m_log.Info("[FileSystemDatabase] Time spent Updating so far: " + TimeToUpdate);
  290. }
  291. /// <summary>
  292. /// Detects if a scene object group from the scene list has moved or changed scale. The green aura
  293. /// that surrounds the object is then moved or scaled with the group.
  294. /// </summary>
  295. public System.Collections.ArrayList UpdateNormalEntityEffects(SceneObjectGroup group)
  296. {
  297. System.Collections.ArrayList auraList = new System.Collections.ArrayList();
  298. if (group == null)
  299. return null;
  300. lock (group.Children)
  301. {
  302. foreach (SceneObjectPart part in group.Children.Values)
  303. {
  304. if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID))
  305. {
  306. ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new Vector3(0,254,0), part.Scale);
  307. ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition();
  308. auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]);
  309. }
  310. }
  311. }
  312. return auraList;
  313. }
  314. #endregion Public Methods
  315. }
  316. }