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